Odoo REST and XML-RPC API Integration Tutorial: Connect Any System
Odoo exposes its entire data model through external APIs, making it possible to integrate with virtually any system---eCommerce platforms, CRM tools, business intelligence software, mobile apps, and custom applications. This tutorial covers all three API protocols (XML-RPC, JSON-RPC, and REST), authentication methods, CRUD operations, and real-world integration patterns with code examples and best practices.
Key Takeaways
- Odoo provides three API protocols: XML-RPC (most mature), JSON-RPC (browser-friendly), and REST (Odoo 19, OpenAPI-compliant)
- All APIs require authentication using database name, username, and password or API key
- CRUD operations follow a consistent pattern across all protocols: search, read, create, write, unlink
- Domain filters use a Polish notation syntax for complex queries
- Pagination, field selection, and batch operations optimize performance for large datasets
API Protocol Comparison
| Feature | XML-RPC | JSON-RPC | REST (Odoo 19) |
|---|---|---|---|
| Maturity | Stable since Odoo 8 | Stable since Odoo 10 | New in Odoo 19 |
| Authentication | Username/password | Session-based | API key or OAuth 2.0 |
| Documentation | Manual | Manual | Auto-generated OpenAPI |
| Response format | XML | JSON | JSON |
| Batch operations | Yes | Yes | Yes |
| Webhooks | No (requires custom module) | No | Yes (configurable) |
| Language support | Any (XML-RPC is universal) | JavaScript-friendly | Any (HTTP standard) |
Authentication
XML-RPC Authentication
XML-RPC authentication uses a two-step process: authenticate to get a user ID (uid), then use that uid for subsequent calls.
The authentication call hits the /xmlrpc/2/common endpoint with authenticate method, passing the database name, username, password, and an empty object. The response is the numeric user ID. All subsequent data calls use /xmlrpc/2/object with execute_kw method, passing the database, uid, password, model name, method name, and arguments.
JSON-RPC Authentication
JSON-RPC uses session-based authentication through the /web/session/authenticate endpoint. The request body is a JSON object with jsonrpc: "2.0", a method of call, and params containing db, login, and password. The response includes a session ID in the cookie that authenticates subsequent requests.
REST API Authentication (Odoo 19)
The REST API supports API keys generated in the Odoo backend:
- Navigate to Settings > Users > API Keys
- Generate a new key with specified permissions
- Include the key in the
Authorization: Bearerheader
REST endpoints follow the pattern /api/{model} for collections and /api/{model}/{id} for individual records.
CRUD Operations
Search and Read
The most common operation is searching for records with specific criteria and reading their field values.
Domain filters use Polish notation (prefix notation) with operators:
| Operator | Description | Example |
|---|---|---|
= | Equals | ['state', '=', 'sale'] |
!= | Not equals | ['state', '!=', 'draft'] |
> | Greater than | ['amount_total', '>', 1000] |
< | Less than | ['date_order', '<', '2026-01-01'] |
>= | Greater or equal | ['qty_available', '>=', 10] |
in | In list | ['state', 'in', ['sale', 'done']] |
like | Pattern match | ['name', 'like', 'ECOSIRE'] |
ilike | Case-insensitive pattern | ['email', 'ilike', '@gmail.com'] |
Combining conditions: Use & (AND), | (OR), and ! (NOT) as prefix operators:
- AND:
['&', ['state', '=', 'sale'], ['amount_total', '>', 1000]]matches sale orders over 1000 - OR:
['|', ['state', '=', 'sale'], ['state', '=', 'done']]matches either state - Complex:
['&', ['state', '=', 'sale'], '|', ['partner_id', '=', 5], ['partner_id', '=', 10]]
Field selection: Request only the fields you need to reduce payload size and improve performance. Pass a fields parameter with a list of field names. If omitted, all fields are returned.
Pagination: Use offset and limit parameters to paginate results. Example: offset: 20, limit: 20 returns records 21-40.
Create Records
Create records by calling the create method with a dictionary of field values. Required fields must be included. The response returns the ID of the newly created record (or an array of IDs for batch creation).
Example: Creating a contact requires at minimum the name field. Optional fields include email, phone, company_id, street, city, state_id, country_id, and custom fields.
For related records (one2many or many2many), use special command tuples:
| Command | Syntax | Description |
|---|---|---|
| Create | [0, 0, {values}] | Create a new related record |
| Update | [1, id, {values}] | Update an existing related record |
| Delete | [2, id, 0] | Delete a related record |
| Unlink | [3, id, 0] | Remove the link (don't delete) |
| Link | [4, id, 0] | Add a link to existing record |
| Replace | [6, 0, [ids]] | Replace all links with provided IDs |
Update Records
Update records by calling the write method with the record ID(s) and a dictionary of changed fields. Only include fields that need to change---omitted fields retain their current values.
Batch updates are supported: pass a list of IDs to update multiple records with the same values in a single call.
Delete Records
Delete records by calling the unlink method with the record ID(s). The method returns True on success.
Be cautious with deletion---many Odoo records are protected by business rules. Attempting to delete a posted invoice, for example, will raise an error. Use the appropriate business method instead (e.g., button_cancel before deletion).
Real-World Integration Patterns
eCommerce Order Sync
Synchronize orders from an external eCommerce platform to Odoo:
- Poll for new orders: Query the eCommerce API for orders since the last sync timestamp
- Match customers: Search Odoo contacts by email; create if not found
- Create sales order: Build the order with customer, lines, shipping, and payment info
- Confirm order: Call
action_confirmto process the order through the workflow - Update eCommerce: Send the Odoo order reference back to the eCommerce platform
Inventory Sync
Keep inventory levels synchronized between Odoo and an external channel:
- Read stock levels: Call
search_readonstock.quantwith location filters - Push updates: Send quantity changes to the external channel
- Handle reservations: Account for reserved stock (committed to pending orders)
- Schedule sync: Run every 15-30 minutes to maintain accuracy
CRM Lead Import
Import leads from marketing platforms into Odoo CRM:
- Fetch leads: Pull new leads from the marketing platform API
- Deduplicate: Search Odoo for existing contacts by email or phone
- Create leads: Create records in
crm.leadwith source tracking - Assign: Use Odoo's lead assignment rules or assign based on custom logic
Financial Data Export
Export financial data to a business intelligence platform:
- Export chart of accounts: Read
account.accountfor the account structure - Export journal entries: Read
account.move.linewith date filters - Export balances: Use
read_groupto aggregate balances by account and period - Schedule: Run daily after the accounting close window
Error Handling
Common API Errors
| Error | Cause | Resolution |
|---|---|---|
| Access Denied | Invalid credentials or permissions | Verify username, password, and access rights |
| Record not found | Invalid ID in read/write/unlink | Verify the record exists with a search first |
| Validation Error | Missing required fields or invalid values | Include all required fields with valid data |
| UserError | Business rule violation | Check the error message for specific rule |
| ConcurrencyException | Record modified by another user | Re-read the record and retry |
Rate Limiting
Odoo does not enforce API rate limits by default, but production deployments should implement rate limiting at the reverse proxy level. For Odoo.sh, default limits apply to prevent abuse. Design integrations with reasonable polling intervals and batch operations.
Retry Strategy
Implement exponential backoff for transient errors:
- First retry after 1 second
- Second retry after 4 seconds
- Third retry after 16 seconds
- Log and alert after maximum retries
Performance Optimization
Batch Operations
Prefer batch operations over individual record processing:
createaccepts a list of value dictionaries for batch creationwriteaccepts a list of IDs for batch updatessearch_readwith pagination is more efficient than individualreadcalls
Field Selection
Always specify the fields parameter to avoid loading unnecessary data. Loading all fields on a model with 50+ columns creates significant overhead, especially for models like sale.order or account.move.line.
Caching
Cache slowly changing data locally:
- Product catalog (refresh hourly)
- Customer list (refresh on change notification)
- Tax rates and fiscal positions (refresh daily)
ECOSIRE Integration Services
Building reliable integrations requires understanding both the external system and Odoo's data model. ECOSIRE's Odoo integration services cover API design, connector development, data mapping, and ongoing monitoring. For organizations connecting eCommerce platforms, our specialized Shopify-Odoo integration and marketplace connectors handle the most common scenarios.
Related Reading
- Odoo API Integration Guide
- ETL Pipelines for ERP Data: Odoo and Shopify
- Docker Odoo Deployment Guide
- Odoo Custom Module Development Guide
- API Security: Authentication and Authorization
Which API protocol should I choose for a new integration?
For new projects on Odoo 19, use the REST API. It follows HTTP standards, has auto-generated documentation, and supports API keys for authentication. For Odoo 17 or 18, XML-RPC is the most reliable and well-documented option. JSON-RPC is best for browser-based integrations or JavaScript applications.
Is there a rate limit on Odoo's external API?
Odoo itself does not enforce rate limits. However, Odoo.sh deployments have infrastructure-level limits, and self-hosted deployments should implement rate limiting at the reverse proxy (Nginx) level. Design integrations to use batch operations and reasonable polling intervals regardless of limits.
Can I trigger workflows (confirm order, post invoice) through the API?
Yes. Use the execute_kw method with the workflow method name. For example, call action_confirm on a sale.order to confirm it, or action_post on an account.move to post a journal entry. The workflow methods enforce the same business rules as the UI.
Written by
ECOSIRE Research and Development Team
Building enterprise-grade digital products at ECOSIRE. Sharing insights on Odoo integrations, e-commerce automation, and AI-powered business solutions.
Related Articles
API-First Strategy for Modern Businesses: Architecture, Integration, and Growth
Build an API-first strategy that connects your business systems, enables partner integrations, and creates new revenue opportunities through platform thinking.
Building AI-Powered Business Workflows: From Manual Processes to Intelligent Automation
Design and build AI-powered workflows that automate multi-step business processes across sales, operations, finance, and customer service systems.
CRM Integration Patterns: Connecting Your Sales Ecosystem
Implement CRM integration patterns for ERP, marketing, support, and e-commerce systems with best practices for data sync, architecture, and error handling.