There is an important correction developers should know before planning an Odoo 20 integration migration:
Odoo did not remove every legacy XML-RPC/JSON-RPC external service in Odoo 20.
Current official documentation says:
- the legacy
dbservice was removed in Odoo 20; - the
commonandobjectservices are deprecated and currently scheduled for removal in Odoo 22; - External JSON-2 is the replacement direction.
Older Odoo material and third-party articles may show an earlier timeline. Use the current official documentation when planning production work.
What is actually deprecated?
Odoo’s deprecation applies to the legacy external RPC endpoints/services.
Do not automatically assume every custom JSON controller in an Odoo module is removed because “JSON-RPC is deprecated.”
Custom application controllers and the legacy external API surface are separate concepts and must be reviewed against the current controller documentation.
Why migrate before removal?
Waiting until the final removal release creates unnecessary pressure.
Migrating earlier gives you time to:
- inventory undocumented clients;
- create contract tests;
- redesign authentication;
- reduce privileges;
- fix poor integration patterns;
- run old/new paths in controlled comparison;
- upgrade client libraries.
The migration is also an opportunity to stop exposing Odoo’s generic model layer more broadly than necessary.
Step 1 — Find every legacy client
Search code and infrastructure for:
/xmlrpc;/xmlrpc/2;/jsonrpc;common;object;db;execute_kw;- old Odoo RPC libraries;
- cron scripts;
- ETL jobs;
- mobile backends;
- middleware;
- spreadsheets/automation scripts.
Do not forget integrations owned by another department or vendor.
Create an inventory:
| Integration | Endpoint/service | Operations | Owner | Criticality | Replacement |
|---|---|---|---|---|---|
| Mobile backend | object | read/create | Mobile | High | JSON-2 |
| ETL | object | read | Data | Medium | JSON-2 |
| DB utility | db | database ops | DevOps | High | Redesign |
Anything using db deserves immediate attention for Odoo 20 because current docs state that service is removed.
Step 2 — Document the current contract before rewriting it
For each client, capture:
- authentication;
- model/methods;
- domains;
- fields;
- context;
- pagination;
- write payloads;
- expected errors;
- retry behavior;
- time-zone handling;
- binary/document handling.
Then write tests around the behavior.
A migration without a known old contract becomes “the new integration seems to work.”
That is not enough for a critical system.
Step 3 — Re-evaluate privileges
Legacy integrations often run with users that accumulated excessive permissions.
Use the migration to create a least-privilege integration user.
Test:
- access rights;
- record rules;
- multi-company boundaries;
- archived records;
- sensitive models.
Do not replace an old administrator credential with a new administrator API key and call it modernization.
Step 4 — Map operations to JSON-2
Use current official JSON-2 documentation to map each required operation.
Avoid translating calls mechanically if the old integration has poor architecture.
For example, if a client performs five low-level writes to simulate one business operation, consider exposing/calling a validated Odoo method that performs the operation atomically.
Preserve business semantics, not obsolete request structure.
Step 5 — Design for transaction boundaries
Separate HTTP calls are separate failure points.
If operation B must never happen without operation A, consider implementing a server-side business method that performs both under Odoo’s transaction/business rules.
Do not make an external client responsible for reconstructing internal ERP invariants.
Step 6 — Improve error handling
Legacy integrations often treat every failure as “RPC error.”
The new client should classify:
- authentication;
- authorization;
- validation;
- missing record;
- malformed request;
- conflict/business state;
- network/timeout;
- server failure.
Retry only failures that are actually retryable.
Step 7 — Test old vs new behavior
For safe operations, compare:
- records returned;
- fields;
- ordering where relevant;
- domain behavior;
- context/company behavior;
- created values;
- workflow result;
- error semantics.
For write-heavy production systems, use a staging environment rather than double-writing live data.
Step 8 — Cut over with observability
Before switching:
- add request correlation/logging;
- monitor error rates;
- monitor latency;
- define rollback at the client/configuration level where feasible;
- keep the old client available only for the planned transition window;
- remove old secrets/endpoints after stabilization.
Do not leave the deprecated integration running forever “just in case.”
What about Odoo 20 specifically?
Odoo 20 matters because the old db service is already removed according to current official documentation.
For common and object, the immediate issue is not “Odoo 20 breaks everything.” The issue is that they are deprecated with a documented removal direction.
That gives teams a migration window—use it.
What about custom JSON-RPC controllers?
Treat them separately.
If your custom module exposes a route for a mobile app or webhook, inspect the current Odoo HTTP/controller framework and the route implementation.
Do not rewrite a working custom endpoint merely because an unrelated legacy external service shares the words “JSON-RPC.”
The current deprecation timeline
Older articles on this topic can be out of date. The current official timeline is:
| Component | Current status |
|---|---|
/xmlrpc, /xmlrpc/2, /jsonrpc external APIs | Deprecated |
db service | Removed in Odoo 20 |
common service | Scheduled for removal in Odoo 22 |
object service | Scheduled for removal in Odoo 22 |
Custom @route(type='jsonrpc') controllers | Not covered by this deprecation notice |
| Replacement | External JSON-2 API |
Odoo's documentation history confirms the broader removal was originally planned earlier and was postponed. This is why old Odoo 20 articles can now be wrong.
Mapping object RPC to JSON-2
Legacy concept:
object.execute_kw(
database, uid, credential,
model, method, args, kwargs
)JSON-2 concept:
POST /json/2/<model>/<method>
Authorization: bearer <API_KEY>
JSON body with named argumentsThe migration removes the old login/object-call choreography and changes authentication/request shape.
Do not mechanically translate every low-level call. Preserve the business operation.
Special case: the removed db service
Inventory scripts that list, create, drop, duplicate or otherwise administer databases through the old db service.
Do not assume there is a one-for-one JSON-2 model replacement for database administration. Redesign those workflows around currently supported administration/deployment mechanisms.
Should Odoo 20 users panic?
No. If an integration uses only deprecated common/object, Odoo 20 does not automatically mean it stops working. But it is documented technical debt with a removal path.
A sensible sequence is:
inventory → contract tests → JSON-2 client → staging comparison → controlled cutover → revoke legacy credentials.
A migration should preserve semantics, not syntax
A legacy call may look like:
execute_kw(model, method, args, kwargs)The goal is not to produce a line-for-line JSON-2 equivalent.
First ask what business operation the old client is performing.
If the old client:
- searches a customer;
- creates an order;
- creates lines;
- manipulates state;
- triggers another call;
the better target may be a purpose-built Odoo method representing the complete business operation.
This is a chance to simplify the contract.
Run a contract-test suite
For read operations, compare old and new clients against the same staging data:
- record IDs;
- important fields;
- domain filtering;
- context;
- company behavior;
- pagination.
For writes, assert the resulting Odoo state rather than merely comparing HTTP responses.
Example:
Input: external order ABC-123
Expected:
- one Odoo order
- correct customer
- three lines
- expected currency/company
- no duplicate on retryThat is a stronger migration test than “request returned success.”
Plan the cutover per integration
Not every client has to switch on the same day.
A lower-risk sequence can be:
- migrate read-only/reporting clients;
- migrate low-impact writers;
- migrate revenue/operations-critical writers;
- remove old credentials and libraries after stabilization.
This reduces the number of unknowns during an Odoo major-version cutover.
Inventory hidden dependencies
Legacy RPC often survives in unexpected places:
- Excel/VBA;
- scheduled Python scripts;
- old mobile services;
- ETL;
- Zapier-like automation;
- vendor middleware;
- monitoring scripts.
Search source repositories, servers, CI variables and documentation—not only the main application.
FAQ
Is XML-RPC removed in Odoo 20?
Current official documentation says the db service was removed in Odoo 20. Deprecated common and object services are currently scheduled for removal in Odoo 22.
What replaces legacy Odoo RPC?
Odoo’s replacement direction for the external API is JSON-2.
Do we have to migrate during the Odoo 20 upgrade?
Not every legacy common/object integration must necessarily be rewritten during the same cutover, but you should inventory and plan the migration. Anything using the removed db service requires redesign for Odoo 20.
Is MCP the replacement for XML-RPC?
No. MCP serves external AI-tool workflows. JSON-2 is the external application API replacement direction.
Final takeaway
Do not migrate because an old blog says “XML-RPC is gone in Odoo 20.”
Migrate because the legacy APIs are deprecated, one service is already removed, a replacement exists, and controlled modernization is safer than waiting for the final deadline.
Planning an Odoo 20 project? Octivex Tech helps businesses with Odoo upgrades, custom module migration, integrations and AI-enabled workflows. Explore our Odoo services or contact our engineering team to discuss your environment.
