How to Connect to the Odoo API: A Practical Guide
Everything you need to connect to the Odoo API: the four instance coordinates, the two API keys, a first version smoke-test call, and reading a failed connection.
ODXProxy Team · Jul 9, 2026 · 6 min read

Before you can read a single record, you have to establish an Odoo API connection — and most of the
time people get stuck here, on a 401 or a hung request, is because a connection to Odoo needs more than
a URL. This guide walks the whole thing end to end: the four coordinates that identify an Odoo instance,
the two separate API keys involved, a zero-risk first call to prove the pipe is open, and how to read the
handful of failures that mean "not connected." Everything runs over Odoo's JSON-RPC External API through
a single proxy endpoint.
What a connection actually needs
A working connection is really two hops: your code connects to the proxy, and the proxy connects to your Odoo instance. Each hop has its own credential, and the Odoo hop needs four coordinates to locate the exact database and user to act as:
url— the base URL of the Odoo server, e.g.https://erp.example.com.db— the Odoo database name. A server can host several; you must name one.user_id— the integer user id (uid) to act as. Not the login string — the numeric id.api_key— that Odoo user's API key (generated in Odoo under the user's preferences).
Those four travel together in every request, inside an odoo_instance object. The proxy itself is
guarded by its own key:
x-api-key— the proxy's static key, sent as an HTTP header. This is not the Odoo user's key; conflating the two is the single most common connection mistake.
x-api-key gets you past the proxy. The api_key inside odoo_instance gets the proxy into Odoo as a specific user. A request needs both, and a mix-up in either returns an authentication error — see below for telling them apart.The full walkthrough of generating the Odoo user key lives in how to authenticate to the Odoo API.
Prove the pipe is open first
The best way to test a connection is a call that needs almost nothing — so a failure points at exactly one thing. The proxy exposes a version endpoint that only needs the proxy key and the target Odoo URL, no user credentials at all. It's the ideal smoke test:
{
"id": "conn-check-1",
"url": "https://erp.example.com"
}Send that to the version route with your proxy key in the header:
POST /api/odoo/version
x-api-key: <the proxy API key>A healthy connection comes back as a JSON-RPC envelope whose result is Odoo's version_info:
{
"jsonrpc": "2.0",
"id": "conn-check-1",
"result": { "server_version": "18.0", "server_version_info": [18, 0, 0, "final", 0] }
}If that succeeds, you know two things at once: your proxy key is valid and the proxy can physically reach the Odoo server. Only after that do you introduce the database and user credentials.
Your first authenticated call
With the pipe proven, make a real read against the main execute endpoint. Reading one partner is a good
first authenticated call — it exercises the db, user_id, and api_key together:
{
"id": "conn-read-1",
"action": "search_read",
"model_id": "res.partner",
"params": [[["is_company", "=", true]]],
"keyword": { "fields": ["name", "email"], "limit": 1 },
"odoo_instance": {
"url": "https://erp.example.com",
"db": "prod",
"user_id": 2,
"api_key": "<the Odoo user API key>"
}
}POST /api/odoo/execute
x-api-key: <the proxy API key>A single partner in result means the full connection — proxy key, database, user, and user key — is
working end to end. From here, the other eight actions (search, read, create, write, unlink,
search_count, fields_get, and call_method) all use the exact same envelope; only action and the
params/keyword payload change. That shape is laid out in
the one route you actually call.
Reading a failed connection
When a connection doesn't work, the error tells you which hop broke. The two layers report differently, and knowing which is which saves hours:
- Wrong or missing proxy key → HTTP
401, error code-32000. Yourx-api-keyheader is absent or incorrect. This never reaches Odoo. - Proxy can't reach Odoo → HTTP
502, error code-32004(bad gateway). The URL is wrong, DNS fails, or Odoo is down. If the version smoke test above fails this way, fix networking before touching credentials. - Odoo took too long → HTTP
504, error code-32003(timeout). The call reached Odoo but didn't finish inside the window. Tune it with thex-request-timeoutheader (integer seconds; default 15). - Bad Odoo credentials → HTTP
200with a populatederror. This is the one that surprises people: an authentication failure inside Odoo (wrongdb,user_id, or the Odooapi_key) is an Odoo-layer logic error, so it rides back on a200, not a401.
200 is not a green light. Odoo logic errors — including a wrong database or user key — return HTTP 200 with an error object populated. Always check the HTTP status and then the body's error field before you treat a connection as established. Only proxy-layer failures use non-200 codes.That two-step check — status first, then error — is the habit that separates a robust client from one
that silently treats failures as success. The complete code-by-code map and retry guidance is in
Odoo API error handling.
Keeping the connection healthy
A connection isn't just "does it work once" — it's "does it stay usable under real conditions":
- Set a sane timeout. Big reads and heavy
call_methodcalls can outrun the 15-second default. Sendx-request-timeoutwith a larger integer (in seconds) on those calls rather than raising it globally. - Reuse credentials, not connections. There's no session to keep alive — each request carries its own
odoo_instance, so the proxy is effectively stateless from your side. Store the four coordinates securely and send them each time. - Give every request an
id. Theidyou send is echoed back in the response, which makes matching replies to requests (and log correlation) trivial when you're firing many calls.
Where to go next
- Generate and manage the Odoo user key in how to authenticate to the Odoo API.
- See the full set of nine actions on the one route you actually call.
- Understand every failure mode in Odoo API error handling.
- Read the full request and response contract in the API reference, or skip the envelope boilerplate with the Python SDK, which manages the connection details for you.