Skip to content

Authentication

Complete guide to authenticating with the JDX Odoo REST API.

Authentication Methods

Method Use Case Token Lifetime
OAuth2 External integrations 1 hour (configurable)
API Key Server-to-server No expiry
Session PWA / Web browser Session-based

OAuth2 Authentication

Step 1: Get Access Token

curl -X POST "https://{your-erp-domain}/restapi/1.0/common/oauth2/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials" \
  -d "client_id=YOUR_CLIENT_ID" \
  -d "client_secret=YOUR_CLIENT_SECRET"

Response:

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "expires_in": 3600
}

Step 2: Use Access Token

curl -X GET "https://{your-erp-domain}/restapi/1.0/object/res.partner" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

JWT Token Format

Request JWT format by adding token_format=jwt:

curl -X POST "https://{your-erp-domain}/restapi/1.0/common/oauth2/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials" \
  -d "client_id=YOUR_CLIENT_ID" \
  -d "client_secret=YOUR_CLIENT_SECRET" \
  -d "token_format=jwt"

JWT payload contains:

{
  "sub": "user_id",
  "db": "database_name",
  "exp": 1702400000,
  "iat": 1702396400
}

API Key Authentication

Setup in Odoo

  1. Go to Settings → Users & Companies → Users
  2. Select the API user
  3. Go to Preferences tab
  4. Under API Keys, click New API Key
  5. Enter a description and click Generate Key
  6. Copy the key (shown only once)

Security

Store API keys securely. Never commit to git or expose in client-side code.

Using API Key

Header method (recommended):

curl -X GET "https://{your-erp-domain}/restapi/1.0/object/res.partner" \
  -H "X-API-Key: YOUR_API_KEY"

Bearer token method:

curl -X GET "https://{your-erp-domain}/restapi/1.0/object/res.partner" \
  -H "Authorization: Bearer YOUR_API_KEY"

Session Authentication

Used by the PWA and web interface.

Login

curl -X POST "https://{your-erp-domain}/web/session/authenticate" \
  -H "Content-Type: application/json" \
  -c cookies.txt \
  -d '{
    "jsonrpc": "2.0",
    "method": "call",
    "params": {
      "db": "odoo_production",
      "login": "username",
      "password": "password"
    }
  }'

Response:

{
  "jsonrpc": "2.0",
  "result": {
    "uid": 2,
    "session_id": "abc123...",
    "username": "admin",
    "company_id": 1
  }
}

curl -X GET "https://{your-erp-domain}/web/dataset/call_kw" \
  -H "Content-Type: application/json" \
  -b cookies.txt \
  -d '{
    "jsonrpc": "2.0",
    "method": "call",
    "params": {
      "model": "res.partner",
      "method": "search_read",
      "args": [[["is_company", "=", true]]],
      "kwargs": {"fields": ["name", "email"], "limit": 10}
    }
  }'

Code Examples

Python

import requests

# OAuth2
def get_oauth_token(base_url, client_id, client_secret):
    response = requests.post(
        f"{base_url}/restapi/1.0/common/oauth2/token",
        data={
            "grant_type": "client_credentials",
            "client_id": client_id,
            "client_secret": client_secret
        }
    )
    return response.json()["access_token"]

# API Key
def get_partners(base_url, api_key):
    response = requests.get(
        f"{base_url}/restapi/1.0/object/res.partner",
        headers={"X-API-Key": api_key},
        params={
            "domain": "[('is_company','=',True)]",
            "fields": "['name','email','phone']",
            "limit": 50
        }
    )
    return response.json()

# Usage
base_url = "https://your-erp-domain.com"
api_key = "your_api_key"
partners = get_partners(base_url, api_key)

JavaScript (Node.js)

const axios = require('axios');

// OAuth2
async function getOAuthToken(baseUrl, clientId, clientSecret) {
  const response = await axios.post(
    `${baseUrl}/restapi/1.0/common/oauth2/token`,
    new URLSearchParams({
      grant_type: 'client_credentials',
      client_id: clientId,
      client_secret: clientSecret
    })
  );
  return response.data.access_token;
}

// API Key
async function getPartners(baseUrl, apiKey) {
  const response = await axios.get(
    `${baseUrl}/restapi/1.0/object/res.partner`,
    {
      headers: { 'X-API-Key': apiKey },
      params: {
        domain: "[('is_company','=',True)]",
        fields: "['name','email','phone']",
        limit: 50
      }
    }
  );
  return response.data;
}

JavaScript (Browser/PWA)

// Session-based authentication
async function login(database, username, password) {
  const response = await fetch('/web/session/authenticate', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    credentials: 'include',
    body: JSON.stringify({
      jsonrpc: '2.0',
      method: 'call',
      params: { db: database, login: username, password: password }
    })
  });
  return response.json();
}

// Make authenticated request
async function getPartners() {
  const response = await fetch('/web/dataset/call_kw', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    credentials: 'include',
    body: JSON.stringify({
      jsonrpc: '2.0',
      method: 'call',
      params: {
        model: 'res.partner',
        method: 'search_read',
        args: [[['is_company', '=', true]]],
        kwargs: { fields: ['name', 'email'], limit: 10 }
      }
    })
  });
  return response.json();
}

Token Refresh

OAuth2 tokens expire. Refresh before expiry:

curl -X POST "https://{your-erp-domain}/restapi/1.0/common/oauth2/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=refresh_token" \
  -d "refresh_token=YOUR_REFRESH_TOKEN" \
  -d "client_id=YOUR_CLIENT_ID" \
  -d "client_secret=YOUR_CLIENT_SECRET"

Error Responses

Status Error Description
401 invalid_client Wrong client_id or client_secret
401 invalid_token Token expired or invalid
401 invalid_api_key API key not found or revoked
403 access_denied User lacks permission

Error response format:

{
  "error": "invalid_token",
  "error_description": "The access token has expired"
}

Security Best Practices

  1. Use HTTPS - Never send credentials over HTTP
  2. Store keys securely - Use environment variables, not code
  3. Rotate API keys - Regenerate periodically
  4. Limit permissions - Create dedicated API users with minimal access
  5. Monitor usage - Check logs for unusual API activity

Next Steps