Skip to main content
Odoo 20 JSON-2 API: A Practical Integration Guide
8 min read
Odoo

Odoo 20 JSON-2 API: A Practical Integration Guide

Understand Odoo 20 JSON-2 API architecture, authentication, transactions, migration from legacy RPC and when to use JSON-2 vs MCP or custom controllers.

Odoo’s external API direction is moving toward JSON-2.

For developers maintaining mobile apps, middleware, portals, marketplaces or other software connected to Odoo, JSON-2 should be evaluated separately from Odoo’s MCP server and separately from custom HTTP controllers.

The key distinction is simple:

  • JSON-2: deterministic application-to-Odoo API integration.
  • MCP: external AI clients using controlled tools.
  • Custom controller: application-specific HTTP behavior implemented by your module.

Do not treat them as interchangeable.

Why JSON-2 matters in Odoo 20

Odoo introduced JSON-2 as the replacement direction for the deprecated external XML-RPC/JSON-RPC APIs.

Current official documentation says the old db service was removed in Odoo 20, while common and object are deprecated and currently scheduled for removal in Odoo 22.

That means Odoo 20 is a good time to inventory old integrations even if some legacy calls still work.

Start with the official API documentation

Before copying any request example from this article, verify:

  • current endpoint structure;
  • authentication headers;
  • database selection behavior;
  • available model methods;
  • transaction semantics;
  • plan/subscription requirements.

These details can evolve.

Authentication

Use the authentication method documented for the current JSON-2 API.

Store API credentials in a proper secret store or environment configuration.

Never:

  • commit keys to source control;
  • ship privileged server keys inside a mobile binary;
  • log secrets;
  • reuse administrator credentials when a constrained integration user is enough.

For mobile/web clients, consider a backend/middleware layer when exposing a long-lived Odoo credential directly to the client would be unsafe.

Design the integration user

Create an Odoo user with only the access required by the integration.

If an integration only needs:

  • read products;
  • create leads;
  • read its own orders;

do not give it broad Accounting/HR/System permissions.

Odoo access rights and record rules are part of your API security.

JSON-2 transactions

One important integration design principle is transaction scope.

Do not assume a chain of separate HTTP requests behaves like one atomic business operation.

If an operation must be atomic, prefer calling a purpose-built model method that performs the complete validated business operation within Odoo rather than orchestrating many fragile client-side writes.

Example:

Bad integration pattern:

text
create order
→ create lines
→ manually update totals
→ change state
→ create stock data

Better:

text
call a validated Odoo business method
→ let Odoo enforce invariants internally

Use the ORM/business layer instead of reconstructing Odoo logic externally.

Error handling

An integration should distinguish:

  • authentication failure;
  • access denial;
  • validation/business-rule failure;
  • missing record;
  • malformed request;
  • server error;
  • timeout/network failure.

Do not retry every error automatically.

A validation error will not become valid because the client sends it ten more times.

For retryable operations, design idempotency where possible.

Search/read integration design

When retrieving records:

  • request only required fields;
  • paginate/limit intentionally;
  • use domains carefully;
  • avoid huge unbounded searches;
  • account for company/access rules;
  • validate dates/time zones;
  • avoid N+1 request patterns.

For synchronization jobs, store stable identifiers and checkpoints rather than repeatedly downloading the entire database.

Create/update design

For writes:

  • validate payloads before calling Odoo;
  • let Odoo enforce model constraints;
  • avoid arbitrary field pass-through from untrusted clients;
  • restrict writable fields in middleware or purpose-built methods;
  • preserve company context;
  • log correlation IDs where useful.

A generic endpoint that accepts any model/field/value is convenient during development and dangerous in production.

JSON-2 vs custom controller

Use JSON-2 when standard model/business methods provide the interface you need.

Use a custom controller when the external contract should be purpose-built—for example:

  • webhook receiver;
  • public/mobile endpoint with custom authentication;
  • aggregate operation;
  • specialized payload;
  • backwards-compatible external contract.

A custom controller adds maintenance responsibility, so do not build one merely to avoid learning the standard API.

JSON-2 vs MCP

JSON-2 is normally the better choice when the caller already knows exactly what operation to perform.

MCP is useful when an AI client needs to interpret natural language and choose among approved tools.

A payment gateway callback should not ask an LLM what to do.

A developer assistant asked to investigate neglected opportunities may benefit from MCP.

Migration strategy from legacy RPC

Inventory every legacy client:

ClientLegacy serviceCriticalityOwnerJSON-2 plan
Mobile appobjectHighMobilePlanned
ETLobjectMediumDataPlanned
Admin scriptdbHighDevOpsMust replace for Odoo 20

Prioritize anything using the removed db service.

Then build contract tests so old and new integrations can be compared.

Testing checklist

  • authentication;
  • access rights;
  • record rules;
  • multi-company;
  • CRUD/business methods;
  • validation errors;
  • time zones;
  • binary/documents;
  • pagination;
  • retries;
  • duplicate prevention;
  • network failures;
  • concurrency;
  • performance;
  • audit/logging.

JSON-2 request structure

Current Odoo documentation places the model and method in the URL:

text
POST /json/2/<model>/<method>

Authentication uses a Bearer API key.

A documented read pattern looks like:

python
import requests

response = requests.post(
    "https://your-odoo.example.com/json/2/res.partner/read",
    headers={"Authorization": f"bearer {API_KEY}"},
    json={
        "ids": [1, 2, 3],
        "context": {"lang": "en_US"},
        "fields": ["name"],
        "load": None,
    },
)

data = response.json()

Where one domain serves multiple databases, Odoo documents X-Odoo-Database as potentially required.

Dedicated bot users

Odoo recommends dedicated bot users for extended automated usage.

Benefits include minimum required permissions, clearer access-log attribution, independent revocation, and the option to disable password login for the bot.

Prefer a separate API key per integration where practical.

API-key lifecycle

Current documentation supports scopes and expiration dates. A production rotation flow should be:

  1. create a new key;
  2. deploy it to the integration;
  3. verify traffic uses it;
  4. revoke the previous key.

Name keys by service so an incident responder can identify ownership.

How JSON-2 differs from legacy object RPC

Current Odoo docs identify key changes:

  • model and method are placed in the URL;
  • login/password authentication becomes Bearer API-key authentication;
  • arguments are named in the JSON body;
  • database identification is only separately required in certain multi-database deployments.

Treat migration as an API-client refactor, not a string replacement.

Access rights still apply

Odoo states JSON-2 operations are validated against the user's access rights, record rules and field access.

This makes least-privilege bot-user design part of the API architecture, not an optional hardening step.

Build a stable integration layer

A robust integration should not scatter raw Odoo calls throughout an application.

Create a small client/service layer responsible for:

  • authentication;
  • base URL/database configuration;
  • request construction;
  • timeout policy;
  • error normalization;
  • retries;
  • logging/correlation;
  • serialization;
  • pagination.

Then business code can call operations such as:

text
odooCustomers.search(...)
odooOrders.create(...)
odooInvoices.getStatus(...)

instead of duplicating transport logic everywhere.

Avoid client-side reconstruction of Odoo business logic

If an integration needs to confirm a sale, create delivery consequences and produce accounting effects, do not manually reproduce internal steps through arbitrary writes.

Prefer supported Odoo business methods or a purpose-built server-side method that keeps the operation inside one validated business transaction.

This reduces the chance that an external client leaves Odoo in a state the normal UI could never create.

Idempotency and duplicate prevention

External systems retry.

Design write integrations so a timeout does not create duplicate:

  • leads;
  • orders;
  • payments;
  • shipments;
  • invoices.

Common patterns include storing an external immutable identifier and checking it before creating a new record.

The exact implementation depends on the business object, but duplicate prevention should be designed before production.

Performance considerations

For high-volume integrations:

  • batch logically where the API/business method supports it;
  • avoid requesting unused fields;
  • avoid per-record N+1 calls;
  • paginate;
  • cache stable reference data appropriately;
  • measure real latency;
  • respect Odoo worker/infrastructure capacity.

A technically valid API client can still overload an ERP if it repeatedly performs expensive searches.

Integration security checklist

  • dedicated least-privilege user;
  • secret manager/environment configuration;
  • no API key in mobile/frontend source;
  • TLS;
  • access/record-rule tests;
  • company-context tests;
  • payload validation;
  • rate/abuse controls where applicable;
  • redacted logs;
  • credential rotation process.

FAQ

Is JSON-2 the Odoo 20 API?

It is Odoo’s current external API replacement direction for deprecated XML-RPC/JSON-RPC services. Odoo can also expose custom controllers and MCP for different use cases.

Were XML-RPC and JSON-RPC removed in Odoo 20?

Not entirely. Current official documentation says db was removed in Odoo 20, while deprecated common and object services are currently scheduled for removal in Odoo 22.

Should I use MCP instead of JSON-2?

Use MCP for external AI-tool workflows. Use JSON-2 for deterministic application integration.

Should a mobile app contain an Odoo API key?

Be cautious with long-lived privileged secrets in distributable clients. A backend/middleware architecture may be safer depending on the application and threat model.

What is the endpoint format?

/json/2/<model>/<method> in current official documentation.

Does JSON-2 respect record rules?

Yes. Standard Odoo security applies to the authenticated user.

When is X-Odoo-Database needed?

For certain deployments where a domain/server hosts multiple databases and host routing/dbfilter does not uniquely select one.

Final takeaway

The most important JSON-2 migration principle is not endpoint syntax.

It is to keep business invariants inside Odoo, minimize privileges, define stable integration contracts and test failure behavior—not just successful requests.


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.