HADOOPT
TECHNOLOGIES
Schedule a Tech Consultation
Home
Services
Odoo ERP implementation Rollout, custom modules, migration and support. Web application development SaaS products, portals and internal platforms. Mobile application development Offline-first field apps and customer apps. AI development & automation LLM assistants, document processing, forecasting. Odoo version upgrades ↗ Move to a newer release, scoped and priced on its own site.
Products
OrgExp ↗ Budget, CAPEX and OPEX management.
Blog About Contact Schedule a Tech Consultation
Blog / Odoo implementation
Implementation 8 min read

Odoo's API for integrations: JSON-2, XML-RPC, webhooks and MCP

How to integrate with Odoo 19 and 20: the JSON-2 API, the deprecated XML-RPC and JSON-RPC endpoints, API keys, webhooks in automation rules, and MCP.

· ERP practice 12 Nov 2026

New integrations with Odoo 19 or 20 should use the JSON-2 API: an HTTP POST to /json/2/<model>/<method> with an API key as a bearer token. The older XML-RPC and JSON-RPC endpoints still work but are deprecated, and Odoo's documentation schedules their removal for Odoo 22 (fall 2028) and Odoo Online 21.1 (winter 2027). For events, automation rules can send and receive webhooks. For AI tools, Odoo 20's AI app includes an MCP server.

This post explains each piece and when to use it. It builds on our Odoo 20 readiness checklist, which flags the RPC deprecation as work to plan now.

The four ways in and out of Odoo

MechanismDirectionUse it forAvailable from
JSON-2 APIOther system calls OdooReading and writing records, calling business methodsOdoo 19
XML-RPC / JSON-RPCOther system calls OdooExisting integrations onlyLong-standing; deprecated, removal planned for Odoo 22
Webhooks in automation rulesBoth: Odoo receives a call, or Odoo sends one when a record changesSimple event pushes and pullsOdoo 17 onwards (Community module base_automation)
MCP serverAI client calls Odoo toolsLetting Claude, ChatGPT or similar agents read and act on dataOdoo 20 AI app

On Odoo Online, the documentation adds a plan condition: external API access is only available on the Custom plan, not on One App Free or Standard. Odoo's pricing page only offers Odoo.sh and self-hosted Enterprise on the Custom plan anyway, and Community has no plans at all.

The JSON-2 API in Odoo 19 and 20

JSON-2 exposes the ORM over plain HTTP. Every call is a POST to /json/2/<model>/<method>. The headers are:

  • Authorization: bearer <API key>, required.
  • Content-Type: application/json, required.
  • X-Odoo-Database, needed when one server hosts several databases and the database filter can't pick one from the hostname.
  • User-Agent, recommended, so your integration is recognisable in logs.

The body is a JSON object. ids holds the records to act on (leave it out for model-level methods such as search), context is optional, and every method argument is passed by name. A successful call returns HTTP 200 with the method's result as JSON. An error returns a 4xx or 5xx status with a JSON object naming the exception and its message.

import requests

BASE_URL = "https://erp.example.com/json/2"
API_KEY = ...  # load from a secret store, never from source code
headers = {
    "Authorization": f"bearer {API_KEY}",
    "X-Odoo-Database": "mycompany",
    "User-Agent": "warehouse-sync " + requests.utils.default_user_agent(),
}

# Customers that are companies, with name and email, in one call
res = requests.post(
    f"{BASE_URL}/res.partner/search_read",
    headers=headers,
    json={
        "domain": [["is_company", "=", True]],
        "fields": ["name", "email"],
        "limit": 20,
        "context": {"lang": "en_US"},
    },
)
res.raise_for_status()
for partner in res.json():
    print(partner["id"], partner["name"], partner["email"])
A JSON-2 call with Python's requests library. The domain, fields and limit are search_read's own arguments, passed by name.

One call, one transaction

This is the design point most likely to catch out a developer used to XML-RPC. Odoo's documentation says each JSON-2 call runs in its own database transaction, committed on success and rolled back on error, and that you cannot chain several calls inside one transaction. If you create an order, then add lines, then confirm it in three calls, a failure halfway leaves a half-built order.

The fix Odoo recommends is to call a single method that does all the related work. Sometimes that's an existing one, such as search_read instead of search then read, or a business method such as action_confirm on a sales order. When no method exists, write one in a small custom module and call that.

API keys and integration users

Create a key under Preferences > Account Security > New API Key. Odoo asks for a description and a duration. Keys cannot last more than three months, so a long-running integration has to rotate its key at least quarterly. The key is shown once; store it in your secret manager straight away.

Keys can also be managed by code: res.users.apikeys has generate and revoke methods. By default only users with Settings administration rights can call them; the system parameter base.enable_programmatic_api_keys opens that up. The documented rotation order is to generate the new key, switch the service to it, check it works, then revoke the old one.

The API enforces normal Odoo security: access rights, record rules and field access all apply to the key's user. Odoo recommends dedicated "bot" users for automated integrations, with only the permissions they need and an empty password so nobody can log in as them interactively. One user and one key per integration also makes it obvious in the logs which system changed a record.

Moving existing XML-RPC and JSON-RPC integrations

The deprecated endpoints are /xmlrpc, /xmlrpc/2 and /jsonrpc, covering the common, db and object services. Your own controllers declared with type='jsonrpc' (called type='json' up to Odoo 18) are not affected.

Odoo's migration notes map the old calls onto the new ones:

  • execute_kw becomes a JSON-2 call: model and method move into the URL, and positional arguments become named ones.
  • Logging in with a password is replaced by the API key in the Authorization header. To find the current user, call res.users/context_get.
  • version() is replaced by /web/version.

A straightforward integration is mostly a rewrite of its call layer, but the transaction rule above can force a redesign if the old code relied on many small calls. Moving to Odoo 20 does not force the change. Rebuilding before the removal date does.

Webhooks with automation rules

Webhooks need no external code on the Odoo side. Both directions are built into automation rules, which are part of Community. Studio gives them a friendlier screen, and in Community you find them in developer mode under Settings > Technical > Automation > Automation Rules.

Incoming: a rule with the trigger On webhook gets a generated URL of the form /web/hook/<uuid>. Another system POSTs JSON to it, and the rule's actions run on the target record. The URL is the only secret, so treat it like a password; Rotate Secret replaces it, and Log Calls records requests for troubleshooting.

Outgoing: the server action Send Webhook Notification POSTs a JSON body to a URL you set, with _model, _id, _action and any fields you pick. Reading Odoo 19's source, it is sent only after the transaction commits, with a one-second timeout and no retry. It is fine for notifying a system that something changed. For anything that must arrive, have the receiver confirm by reading back through JSON-2, or use a queue.

POST https://hooks.example.com/odoo/orders
Content-Type: application/json

{"_action": "Notify warehouse(#41)", "_id": 1873, "_model": "sale.order", "amount_total": 48500.0, "name": "S01873", "state": "sale"}
The shape of an outgoing webhook body, with three fields selected on the action. Odoo adds the three underscore keys.

MCP: connecting AI tools to Odoo

MCP (Model Context Protocol) is an open standard that lets an AI assistant call tools in another system. In Odoo 20, the AI app makes the database an MCP server at <your database URL>/mcp. Odoo's documentation shows connecting Claude Code, Claude Desktop, ChatGPT, Codex, Grok and Google Antigravity, using OAuth (recommended, internal users only) or an API key with the MCP scope.

The tools the AI can call are server actions. By default Odoo exposes a small read-oriented set: get models, get fields, search, read group and an initial-context tool. Anything else has to be switched on per action with the Available in MCP checkbox, and Readonly Tool tells the client it may run that tool without asking the user first. Every connection appears as an API key in the user's preferences, where you revoke it. The AI app is an Enterprise app, and installing it on the Standard plan triggers an upsell to Custom.

Our Odoo 20 release notes post covers the rest of the AI changes. On Odoo 19 and earlier there is no built-in MCP server; that is the gap our own Odoo MCP integration for Claude fills.

An AI client can only do what its Odoo user can do. Give it its own user, with the narrowest rights that still answer the question.

For marketplace integrations built on these APIs, see our Shopify and Amazon post. To plan your integrations with us, get in touch.

Questions we get asked

Is Odoo's XML-RPC API deprecated?

Yes. Odoo's external API documentation says the XML-RPC and JSON-RPC endpoints at /xmlrpc, /xmlrpc/2 and /jsonrpc are deprecated and scheduled for removal in Odoo 22 (fall 2028) and Odoo Online 21.1 (winter 2027). They still work in Odoo 19 and 20. New integrations should use the JSON-2 API that Odoo 19 introduced at /json/2, authenticated with an API key as a bearer token.

How do I authenticate to the Odoo JSON-2 API?

Create an API key under Preferences, Account Security, New API Key, and send it in the Authorization header as "bearer" followed by the key. Keys last at most three months, so plan to rotate them. Add an X-Odoo-Database header if the server hosts several databases. Odoo recommends a dedicated integration user with minimal access rights rather than a person's own account.

Can Odoo send webhooks when a record changes?

Yes. Create an automation rule on the model with the trigger you need, such as a stage change, and add a Send Webhook Notification action with the target URL and the fields to include. Odoo posts JSON with the model, record ID and chosen fields after the transaction commits. It uses a short timeout and does not retry, so the receiving system should tolerate a missed call.

Does Odoo support MCP for AI assistants?

Odoo 20 does, through its AI app. The database acts as an MCP server at your database URL followed by /mcp, and clients such as Claude Code, Claude Desktop, ChatGPT and Codex connect with OAuth or an API key with the MCP scope. Only a small set of read-oriented tools is exposed by default; other server actions must be marked Available in MCP individually.

← Previous Running Odoo on-premise: backups, monitoring and performance tuning Next → Odoo for Indian manufacturers: BOMs, job work, work centres and costing
Keep reading
Implementation Connecting Odoo with Shopify and Amazon: connectors, sync and source of truth 8 min read Implementation Connecting WhatsApp to Odoo: the official app vs third-party connectors 7 min read Implementation Odoo Studio vs custom modules: the costs of each for upgrades, Git and licensing 7 min read