All posts
Developer6 min read

Odoo API Keys: External Authentication Without Storing Passwords

Odoo API keys allow external systems to authenticate via JSON-RPC without storing a user password. This guide covers key generation, scoping, rotation, and the difference between API key auth and session-based auth.

Odoo 14 introduced API keys as a first-class authentication mechanism. An API key is a long random token associated with a specific user. It grants the same access as that user's password but can be revoked independently, generated per integration, and never exposes the user's actual password.

Generating an API Key#

My Profile → Account Security → API Keys → New API Key

  1. Enter a label (e.g., "Production ERP Sync")
  2. If 2FA is enabled, enter the current TOTP code
  3. Copy the key from the dialog - it is shown once and not stored in recoverable form

Store it in a secrets manager, not in a config file.

Using an API Key in XML-RPC#

python
import xmlrpc.client

url = 'https://your-odoo.example.com'
db = 'mydb'
username = 'integration@example.com'
api_key = 'your_api_key_here'

common = xmlrpc.client.ServerProxy(f'{url}/xmlrpc/2/common')
uid = common.authenticate(db, username, api_key, {})

models = xmlrpc.client.ServerProxy(f'{url}/xmlrpc/2/object')
result = models.execute_kw(db, uid, api_key, 'sale.order', 'search_read',
    [[['state', '=', 'sale']]], {'fields': ['name', 'partner_id', 'amount_total']})

The API key is passed wherever the password would go.

JSON-RPC (HTTP) with API Key#

python
import requests

session = requests.Session()
session.post(
    'https://your-odoo.example.com/web/session/authenticate',
    json={'jsonrpc': '2.0', 'method': 'call', 'params': {
        'db': 'mydb',
        'login': 'integration@example.com',
        'password': 'your_api_key_here',
    }}
)
result = session.post(
    'https://your-odoo.example.com/web/dataset/call_kw',
    json={'jsonrpc': '2.0', 'method': 'call', 'params': {
        'model': 'res.partner', 'method': 'search_read',
        'args': [[['customer_rank', '>', 0]]],
        'kwargs': {'fields': ['name', 'email']},
    }}
)

API Key vs Password Auth#

API KeyPassword
Revocable independentlyYesNo
Multiple per userYesNo
Works with 2FA-enabled accountsYes (bypasses TOTP)No
Visible to adminLabel onlyNever
ExpiryManual onlyPassword policy

API keys bypass TOTP because external systems cannot enter a 6-digit code interactively.

Scoping: Use Dedicated Integration Users#

  1. Create a dedicated user: integration@example.com
  2. Assign only the groups needed (e.g., Inventory / User, not full admin)
  3. Generate one API key per external system
  4. Label keys descriptively: "WMS Sync - Prod"

Listing and Revoking Keys#

Users see their keys under My Profile → Account Security → API Keys. Click the trash icon to revoke immediately.

python
env['res.users.apikeys'].sudo().search([
    ('user_id', '=', user.id),
    ('name', '=', 'Old Integration Key'),
]).unlink()

Common Mistakes#

  • Storing keys in git - use a secrets manager; committing keys is a security incident even in private repos
  • Using an admin user for integrations - a leaked admin key is a full compromise; use least-privilege dedicated users
  • Not labeling keys - unlabeled keys become impossible to audit; record the system, environment, and date
  • Forgetting to rotate after personnel changes - revoke keys provisioned by developers who leave; there is no automatic expiry

Try ERPeek on your own Odoo module - ask questions, scaffold tests, and explore your codebase in plain language.

Get started free