Anyone who has ever connected something to Odoo — a webshop, a BI tool, a script of their own — has almost certainly used XML-RPC. That API has been around since the OpenERP days, and that era is coming to an end: from Odoo 19 onwards, XML-RPC and its sibling JSON-RPC are officially deprecated. The replacement is called JSON-2: a modern HTTP+JSON API that is simpler than what it replaces.
The timeline
The old endpoints will keep working for now, but their removal has been announced:
| Deprecated | Removed | |
|---|---|---|
| Self-hosted / Odoo.sh | Odoo 19 | Odoo 22 (autumn 2028) |
| Odoo Online | Odoo 19 | version 21.1 (winter 2027) |
The endpoints affected are /xmlrpc, /xmlrpc/2 and /jsonrpc. If you run self-hosted, you decide when to upgrade and you have the most room to manoeuvre. On Odoo Online you are upgraded automatically — there, winter 2027 is a hard deadline.
What changes
The JSON-2 API breaks with XML-RPC's conventions:
- Authentication with an API key — no more login/password flow with
authenticate(), but anAuthorization: bearerheader with an API key (which you create in your user profile under API keys). - Model and method in the URL — you call
/json/2/<model>/<method>instead of sending everything through one genericexecute_kw. - Named arguments only — all arguments go into the request body as a JSON object (with
idsandcontextas fixed fields). Positional arguments no longer exist; that removes a whole class of subtle bugs. - Real HTTP status codes — errors come back as 4xx/5xx with a JSON error object, instead of a fault wrapped in a 200 response.
- Built-in documentation — every database gets a
/docpage where you can explore the available models and methods and try out example requests.
Old and new side by side
The same call — find the first five companies — in both worlds. First the familiar XML-RPC in Python:
import xmlrpc.client
url, db = "https://odoo.example.nl", "productie"
common = xmlrpc.client.ServerProxy(f"{url}/xmlrpc/2/common")
uid = common.authenticate(db, "gebruiker", "wachtwoord", {})
models = xmlrpc.client.ServerProxy(f"{url}/xmlrpc/2/object")
partners = models.execute_kw(
db, uid, "wachtwoord",
"res.partner", "search_read",
[[["is_company", "=", True]]],
{"fields": ["name", "email"], "limit": 5},
)
And the same thing with JSON-2 — no library needed, any HTTP client will do:
curl -s https://odoo.example.nl/json/2/res.partner/search_read \
-H "Authorization: bearer $ODOO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"domain": [["is_company", "=", true]],
"fields": ["name", "email"],
"limit": 5
}'
Updating records works the same way: ids in the body, the rest as named arguments:
curl -s https://odoo.example.nl/json/2/res.partner/write \
-H "Authorization: bearer $ODOO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"ids": [42], "vals": {"phone": "+31 85 303 9420"}}'
How to approach the migration
- Take stock of your integrations. Not just your own scripts — integration platforms (n8n, Zapier, Make), webshop integrations and BI tools often still speak XML-RPC too. Check your Odoo logs to see which clients come in on
/xmlrpc. - Create API keys per integration, with a dedicated technical user for each one. That way you can limit permissions and revoke access per integration.
- Rewrite the calls to
/json/2/...with named arguments. The methods themselves (search_read,create,write,unlink) stay the same — it is mainly the envelope that changes. - Handle errors by status code instead of by fault parsing; that usually makes error handling simpler than it was.
- Test against
/doc— your own database's built-in API explorer is the fastest way to get a request right.
Tip: combine the migration with your next version upgrade. You will be testing every integration through anyway, and it stops the API migration from ever becoming an emergency job.
Want your integrations built or migrated?
We build and maintain Odoo integrations — from webshops and stock systems to custom integrations — and when we manage your Odoo environment we simply include the API migration in the maintenance plan. Rather do it yourself with a safety net? That works too: we will look over your shoulder on whichever parts you want.