Odoo External API: Authenticate and search_read with XML-RPC and JSON-RPC
Odoo external API XML-RPC authenticate search_read example
Also searched as
- odoo xmlrpc authenticate returns false
- odoo json-rpc call execute_kw python example
- odoo api key instead of password xmlrpc
- odoo external api access denied for model
Short answer
Call the Odoo external API by authenticating against /xmlrpc/2/common to get a user id, then calling execute_kw on /xmlrpc/2/object with the database, uid, password or API key, model name, method and arguments. If authenticate returns False, the database name, login, or API key is wrong, or two-factor is enforced for that user.
Applies to: Odoo 14 to 18 (XML-RPC and JSON-RPC at /jsonrpc); newer releases add a newer JSON API and deprecate XML-RPC, so check your version's external API documentation before building long-lived integrations
How to connect and read data
- 1Create an API key for the integration user: profile > Account Security > New API Key. Use this in place of the password, which also works with two-factor enabled.
- 2Confirm the exact database name. On multi-database servers it is the name in the database manager or the db query parameter, not the company name.
- 3Call common.authenticate(db, login, api_key, {}) at /xmlrpc/2/common. A number is the uid. False means credentials or database are wrong.
- 4Create a models proxy at /xmlrpc/2/object and call execute_kw(db, uid, api_key, model, method, args, kwargs).
- 5Use search_read with a domain list and a fields list, plus limit and offset, to page results.
- 6Create records with create, update with write using a list of ids, and delete with unlink. Always test on a copy of the database first.
- 7Assign a dedicated user with only the access groups the integration needs. Do not use the admin account.
Working Python example with XML-RPC
The code below reads confirmed sale orders. It uses only the Python standard library. The domain uses Odoo prefix notation, which is a list of tuples with implicit AND. Fields you do not list are not returned, which keeps payloads small.
XML-RPC is synchronous and has no connection reuse by default, so create the ServerProxy objects once and reuse them. Large exports should be paged with limit and offset or by id ranges instead of one huge call.
import xmlrpc.client
url = 'https://mycompany.odoo.com'
db = 'mycompany'
login = 'integration@mycompany.com'
api_key = 'YOUR_API_KEY'
common = xmlrpc.client.ServerProxy(url + '/xmlrpc/2/common')
uid = common.authenticate(db, login, api_key, {})
if not uid:
raise SystemExit('Authentication failed')
models = xmlrpc.client.ServerProxy(url + '/xmlrpc/2/object')
orders = models.execute_kw(
db, uid, api_key, 'sale.order', 'search_read',
[[['state', '=', 'sale']]],
{'fields': ['name', 'partner_id', 'amount_total'], 'limit': 50, 'order': 'id desc'}
)
for o in orders:
print(o['name'], o['partner_id'][1], o['amount_total'])JSON-RPC alternative
Odoo also exposes /jsonrpc, which accepts the same service, method and args structure. It is convenient from JavaScript and many integration platforms. The call below mirrors the XML-RPC example: service is object, method is execute_kw, and args repeats db, uid, key, model, method, positional args and kwargs.
Both interfaces enforce the same record rules, access rights and field-level groups as the UI. An integration user that cannot read a model in the UI cannot read it by API either.
curl -s https://mycompany.odoo.com/jsonrpc -H 'Content-Type: application/json' -d '{
"jsonrpc": "2.0", "method": "call", "id": 1,
"params": {
"service": "object", "method": "execute_kw",
"args": ["mycompany", 2, "YOUR_API_KEY", "res.partner", "search_read",
[[["is_company", "=", true]]], {"fields": ["name", "email"], "limit": 5}]
}
}'Why authenticate returns False or the call errors
Wrong database is the most common cause. Odoo Online uses the subdomain as the database name, but many on-premise installs use a different name. Use the db list endpoint (if enabled) or the database manager to confirm. If list_db is disabled, ask your admin.
Using a password for a user with two-factor authentication enabled fails, since only API keys can bypass it. Generate a key and use it as the password argument.
AccessError or AccessDenied on a call usually means the user lacks a group for that model, not that authentication failed. The error text includes the model and operation (read, write, create, unlink) and the record rule involved.
Faults wrapped as xmlrpc.client.Fault contain the Python traceback from the server in faultString. Read the final line for the real cause, such as a required field missing on create.
Practical integration rules
Use many2one values correctly: read returns [id, name] tuples, but create and write expect an integer id. For one2many and many2many fields, use command tuples like (0, 0, vals) to create, (4, id) to link and (6, 0, [ids]) to replace.
Do not poll. For event-driven integrations use automated actions with webhooks (Enterprise and 17+) or scheduled exports, and keep read frequency modest on shared hosting. Respect rate limits on Odoo Online and Odoo.sh.
Store the API key as a secret, rotate it when staff change, and give it an expiry where your version supports key duration.
Common pitfalls
- !Using the company name rather than the database name in authenticate.
- !Using an account password with two-factor enabled instead of an API key.
- !Running the integration as the admin user, which sidesteps access review and logs everything under one identity.
- !Passing [id, name] back to write for a many2one field instead of the integer id.
- !Pulling an entire model in one call with no limit, which times out on large tables.
- !Building a long-lived integration on XML-RPC without checking your version's deprecation notes.
How an ERP-grounded AI assistant handles this
Most integration questions are about the shape of a call: which model, which fields, what domain. An assistant that knows your Odoo instance's model and field definitions can draft the execute_kw call, run it as a read-only query and show you the result and the exact request. With ERPray style read-only access the assistant uses an API key scoped to the integration user. Write calls are proposed, shown and sent only after a person approves.
Frequently asked questions
Does Odoo have a REST API?
Odoo's long-standing external APIs are XML-RPC and JSON-RPC. Recent versions have added a newer JSON based API, and community modules provide REST endpoints. For stable production use, follow the documentation for your exact Odoo version.
How do I get an API key?
Open your user profile, go to Account Security and choose New API Key. Enter a description, confirm your password and copy the key shown. It is displayed once. Use it in place of the password in calls.
Why does search_read return only some records?
Record rules and multi-company settings filter results to what the user can see. Also check a default limit in your code. The API never bypasses rules, so an integration user needs the right company and groups.
Can I call custom methods on a model?
Yes, public methods (not starting with an underscore) can be called through execute_kw. Methods starting with an underscore are private and rejected. Return values must be serializable, so avoid returning recordsets.
Related
Fix Odoo AccessError: You Are Not Allowed to Access Records
Odoo raises AccessError when a user's security groups do not grant a CRUD right on a model through ir.model.access.csv, or when an ir.rule record rule filters the specific record out for that user or company. Fix it by adding the user to the group named in the error, editing the model's access rights, or reviewing the record rule's domain under Settings > Technical > Security.
How-toOdoo Studio Custom Fields: Export, x_studio Names and Upgrade Risk
Odoo Studio saves your changes as data in the database: custom fields named x_studio_*, edited views stored as inherited ir.ui.view records, and automation rules. You can export them as a module via Studio's Export button, but upgrades can break Studio views when the base view changes, and Studio is not a substitute for version-controlled code on complex logic.
Error fixOdoo Scheduled Actions (Cron) Not Running: How to Fix
Odoo scheduled actions usually stop firing because no cron worker is available (workers or max-cron-threads misconfigured), the action is set inactive, or an earlier job crashed and left an ir.cron row stuck in the running state, which blocks the queue. Check Settings > Technical > Automation > Scheduled Actions first, then the server config and the ir.cron table.
How-toHow to Create a Generic Inquiry in Acumatica
Generic Inquiries (GI) are Acumatica's no-code query builder for joining tables, adding filters, and exposing the result as an inquiry screen, dashboard data source, or API endpoint. Open System > Customization > Generic Inquiry, add your base table, define joins and conditions, then run and save. No SQL or customization project is required.
How-toHow to Void a Check in Sage 100
Sage 100 voids checks through Accounts Payable > Main > Check and Payment Voiding. Select the bank code, choose the check number, and Sage reverses the Cash Disbursements Journal entry and reopens the invoice it paid. A check that already cleared in Bank Reconciliation or falls in a closed period needs an extra step before it can be voided cleanly.
How-toHow to Run Requirements Planning (MRP) in SYSPRO
SYSPRO's MRP engine lives under Planning and Scheduling > Requirements Planning. Set planning parameters per warehouse, run the Requirements Calculation to net demand against supply, then review and release the resulting suggestions as purchase requisitions or work orders. A full regenerative run typically runs on a schedule, with net change runs in between to pick up new activity.
AI for ERPAI for Odoo Manufacturing That Reads Your Own Database, Not a Vendor's Cloud
Add grounded, natural-language AI to Odoo Manufacturing without sending MRP, BoM, or work order data to a public model. On-prem or private cloud, ORM-native.
AI for ERPAI for quote-to-cash in manufacturing and job shop ERPs
AI reads incoming RFQs, drafts quotes from your ERP's own cost and pricing history, and flags parts your shop has never quoted before, keeping the estimator in control.
Stuck on Odoo?
Talk to engineers who work inside Odoo every week, and who build private AI that answers these questions from your own ERP data.