If you have scripts or integrations that talk to Odoo over /xmlrpc/2 or /jsonrpc, Odoo 19 already logs a warning every time they run. The warning says those endpoints are scheduled for removal in Odoo 22. They still work in 20, so nothing is on fire. But the replacement works differently enough that it's worth knowing before you have fifteen integrations to move.
Disclosure: I make a paid Odoo module that helps with this (more at the bottom). The rest of this post doesn't need it.
Before
import xmlrpc.client common = xmlrpc.client.ServerProxy(f"{url}/xmlrpc/2/common") uid = common.authenticate(db, login, password, {}) models = xmlrpc.client.ServerProxy(f"{url}/xmlrpc/2/object") rows = models.execute_kw(db, uid, password, "res.partner", "search_read", [[["is_company", "=", True]]], {"fields": ["name"], "limit": 5}) After
import requests rows = requests.post( f"{url}/json/2/res.partner/search_read", headers={"Authorization": f"bearer {api_key}"}, json={"domain": [["is_company", "=", True]], "fields": ["name"], "limit": 5}, ).json() A few things that tripped me up while checking this:
- There's no login call. You make an API key for the user and send it as a bearer token.
- Arguments are named. In XML-RPC you pass them by position, so you have to look at the Python signature of the method to see what each one is called.
search_readtakesdomain,fields,offset,limit,order. - Methods that work on records want an
idskey, e.g.{"ids": [1, 2], "vals": {...}}forwrite. - Only public methods work. Anything starting with an underscore is refused.
- The database isn't in the request. The key decides it.
The annoying part of a migration isn't writing the new call. It's finding every client that still uses the old one. The log tells you something is calling, not who. You can get a rough answer from your reverse proxy's access log by filtering on the three paths.
I wanted more than that (which client, which model, which method, how many times), so I wrote an Odoo module that counts legacy calls and shows the JSON-2 equivalent next to each one. It never stores arguments or passwords. It's called API Migration Checker and it's on the Apps Store: https://apps.odoo.com/apps/modules/19.0/api_migration_checker/
One date caveat: several blog posts say removal happens in Odoo 20. Odoo's own deprecation notice says 22, and I confirmed the endpoints still answer on a 20.0 server.

