Confirm that the database accepts JSON-2 calls, create an API key, and agree which system owns each field. Build and test against a duplicate database before using production.
1. Understand the API and plan requirements
Since Odoo 19, the external API Odoo documents is JSON-2: an HTTP POST to /json/2/<model>/<method> with Content-Type: application/json and Authorization: bearer plus an API key.
Send X-Odoo-Database when more than one database answers on the same domain.
The body is a JSON object of named arguments, plus ids and an optional context. There are no positional arguments.
The models and methods that exist are specific to that database; Odoo says to read them on the database’s /doc page.
Odoo’s pricing page says this inbound API is not included on One App Free or Standard. It defines “External API” as software outside Odoo calling in, and it still names JSON-RPC and XML-RPC in that sentence.
The Odoo 20 developer docs say those two RPC APIs are deprecated: the database service was removed in Odoo 20 (and on Online 19.1), and the common and object services are scheduled for removal in Odoo 22, fall 2028.
A call that Odoo starts, such as a payment provider or a delivery carrier, is not the External API and is part of the Standard plan.
2. Confirm access with a real call
On Odoo Online, an outside system calling Odoo requires the Custom plan. Standard and One App Free do not include it.
On a server you run yourself, the JSON-2 routes are part of Odoo 19 and later; the commercial limit above is Odoo’s statement about its own plans.
Prove access with one real search_read before you design the rest.
3. Create and manage an API key
In Odoo 20, open Preferences → Account Security → New API Key.
- Description: give the key a name that identifies the integration.
- Duration: set an expiry of three months or less. Odoo recommends about one day for interactive use.
- Storage: the key is shown once. Store it securely and keep it out of the code repository.
- Rotation: assign a person to replace the key before it expires.
If you create keys programmatically
Programmatic creation with res.users.apikeys.generate() is limited to Settings administrators unless the system parameter base.enable_programmatic_api_keys is True, and a user can have 10 such keys unless base.programmatic_api_keys_limit says otherwise.
4. Assign one owner per record type
For customers, products, orders, invoices, and stock, name the system that is allowed to change each field. If both sides can write the same field, the next sync is a conflict. Make the other side read that field.
5. Write down the field mapping
Write down each field, its type, and its required values.
A partner on a sales order and a product on a line are relations in Odoo, not flat strings in the other system.
Include units, currencies, taxes, and time zones in that table.
The /doc page of the database lists the fields that exist there, which is more reliable than a generic model list.
6. Choose the event delivery and receiving endpoint
A webhook is an event-delivery pattern, not a requirement to use one particular module. Check what the sending application can emit and what your Odoo hosting allows you to receive.
Built-in Studio webhooks
Where Studio is available, its Webhooks screen can create an incoming webhook and automation. Treat the generated URL as a secret, restrict the target action, enable the needed logging, and test with sanitized payloads in a duplicate database. Rotate the secret if it is exposed.
Custom receivers and JSON-2 calls
On hosting that permits server modules, a compatible connector or custom controller can receive events without Studio. It needs its own authentication, input validation, permissions, and duplicate-handling design. Do not assume Odoo Online accepts that custom code.
An external worker can also call JSON-2 after receiving an event or on a schedule, where your version, plan, and API access permit it. Standard does not gain inbound external API access simply by using a scheduled job.
Choose from required delay, event coverage, hosting constraints, and recovery needs. Reconcile important records periodically so a missed event does not leave the systems permanently out of sync.
7. Make failures visible and retries safe
JSON-2 returns a method result on success and an error response on failure. Handle authentication errors, permission failures, invalid data, rate limits, and temporary outages separately. Keep credentials and unnecessary customer data out of logs.
Each JSON-2 call is its own SQL transaction. Several consecutive API calls do not become one atomic operation. Prefer an appropriate business method that validates and performs related work together, especially for orders, reservations, and payments.
A timed-out write may already have completed. Use stable external identifiers or an agreed idempotency mechanism, inspect the target record after an uncertain result, and retry only through a bounded policy that cannot duplicate the business action. Leave unresolved failures in a queue with an owner and recovery instructions.
8. Test difficult records on a copy
Use a duplicate Odoo database before connecting to a live database, as Odoo’s webhook guide recommends.
- Refunds and cancelled orders
- Partial deliveries and later edits
- Deleted records
- A call that arrives while the worker is down
Compare representative records, mapped values, and business totals as well as counts. Verify access restrictions, retries, and recovery before pointing the integration at production.
9. Plan maintenance after go-live
Because an API key cannot last more than three months, put a rotation date on the calendar.
Odoo’s API page says to prefer a separate key per integration so one service can be revoked with res.users.apikeys.revoke() without stopping the others.
Keep the key out of the repository. Odoo points to the OWASP Secrets Management Cheat Sheet for how to store it.
Move older integrations to JSON-2
If the integration still calls /xmlrpc, /xmlrpc/2, or /jsonrpc, plan the move before the removal release for your hosting: Odoo 22 or Online 21.1.
The database service on those APIs is already gone in Odoo 20.
Re-test after an Odoo upgrade, and keep the field-ownership notes with the code. The /doc page changes when modules are installed or removed.
10. Complete the integration checklist
Write down the answer to every item before starting the production integration.
- The Odoo database is on the Custom plan, or it is a server you operate where JSON-2 is enabled in the version you run
- A real
POST /json/2/...call succeeded with a bearer API key, andX-Odoo-Databasewas set if the host has more than one database - The key has a duration of three months or less, a description, and a written rotation date
- Each shared field has one system allowed to change it
- The field list was taken from that database’s
/docpage, not from a generic example - Studio webhooks, if used, were tested on a duplicate database, and the URL is not in a public place
- A failed call is visible to a person, and a retry cannot create a second record
These API examples target Odoo 20 JSON-2. Older versions and subscription plans can have different capabilities; confirm the API available to your database before building an integration.
11. Frequently asked questions
Can we keep using XML-RPC or JSON-RPC?
Only as a migration. Odoo 20 already removed the database service on /xmlrpc, /xmlrpc/2, and /jsonrpc. The common and object services are scheduled for removal in Odoo 22 and Online 21.1. New work should call JSON-2. The pricing page’s older wording still says “JSON-RPC or XML-RPC” when it defines the External API; the developer documentation is the one that names the replacement.
Do we need Studio for a webhook?
The built-in Studio webhook workflow requires Studio. On hosting that allows server modules, a compatible connector or custom controller can receive events without it. An external worker can also call JSON-2 where API access is available. Odoo Online Standard does not include inbound external API access or Studio.
Is a payment or shipping connector the External API?
No, when Odoo is the side that places the call. Odoo’s pricing answers list payment providers, delivery carriers, VoIP, and bank synchronization as part of the Standard plan. The Custom-plan limit applies when the other software calls Odoo.
12. Related reading and next steps
Tell us what you want to achieve. Email OdooMatrix or chat on WhatsApp (opens a new tab).