Integração da API Odoo: Guia REST, JSON-RPC e XML-RPC
Odoo 19 expõe três interfaces API que cobrem tudo, desde a simples recuperação de dados até a automação complexa de fluxos de trabalho. Esteja você criando um aplicativo móvel personalizado, sincronizando com uma plataforma de terceiros ou ampliando os recursos do Odoo com microsserviços externos, dominar a camada da API do Odoo é fundamental para qualquer projeto de integração sério.
Este guia fornece exemplos de código funcional, fluxos de autenticação e recomendações de arquitetura para integrações REST, JSON-RPC e XML-RPC — as três interfaces principais disponíveis no Odoo 19 Enterprise.
Principais conclusões
- Odoo 19 oferece interfaces REST (OpenAPI 3.0), JSON-RPC 2.0 e XML-RPC
- A autenticação usa chaves API (recomendado) ou login baseado em sessão
- JSON-RPC é a interface mais completa em recursos para operações complexas
- API REST segue as especificações OpenAPI 3.0 e suporta verbos HTTP padrão
- XML-RPC é legado, mas ainda é totalmente compatível para compatibilidade com versões anteriores
- A limitação de taxa e o tratamento de erros devem ser implementados no lado do cliente
- Webhooks no Odoo 19 enviam dados para sistemas externos em alterações de registro
- Todas as chamadas de API respeitam os direitos de acesso e regras de registro do Odoo
Comparação de interfaces de API
Antes de escrever uma única linha de código, escolha a interface API correta para seu caso de uso:
| Recurso | API REST | JSON-RPC | XML-RPC |
|---|---|---|---|
| Protocolo | HTTP/HTTPS | HTTP/HTTPS | HTTP/HTTPS |
| Formato de carga útil | JSON | JSON | XML |
| Especificação OpenAPI | Sim (arrogância) | Não | Não |
| Operações CRUD | Sim | Sim | Sim |
| Chamadas de método | Limitado | Completo | Completo |
| Gatilhos de fluxo de trabalho | Através de ações | Através de execute_kw | Através de executar |
| Recomendado para | Novas integrações | Lógica complexa | Sistemas legados |
| Biblioteca Python | pedidos | odoo-xmlrpc/solicitações | xmlrpc.client |
Quando usar REST: Construindo um aplicativo móvel, integrando com plataformas nativas de webhook (Shopify, Stripe) ou quando sua equipe estiver mais confortável com convenções REST.
Quando usar JSON-RPC: execução de métodos complexos do lado do servidor Odoo, leitura de grandes conjuntos de dados com filtros de domínio ou quando você precisar acessar métodos não expostos via REST.
Quando usar XML-RPC: Manter integrações existentes criadas antes do REST estar disponível ou quando sua plataforma tiver bibliotecas de cliente XML-RPC maduras.
Autenticação
Autenticação de chave de API (recomendado)
Odoo 19 suporta autenticação de chave API para todas as três interfaces. Gere uma chave de API em Configurações → Usuários → Seu usuário → Chaves de API.
import requests
ODOO_URL = "https://your-odoo.com"
API_KEY = "your_api_key_here"
DATABASE = "your_database"
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {API_KEY}"
}
As chaves de API têm como escopo um usuário específico e herdam os direitos de acesso desse usuário. Crie usuários de serviço dedicados com permissões mínimas necessárias para contas de integração.
Autenticação baseada em sessão (JSON-RPC / XML-RPC)
Para JSON-RPC, autentique usando o endpoint /web/dataset/call_kw após estabelecer uma sessão:
import requests
import json
session = requests.Session()
# Authenticate
auth_payload = {
"jsonrpc": "2.0",
"method": "call",
"params": {
"db": "your_database",
"login": "admin",
"password": "your_password"
}
}
response = session.post(
f"{ODOO_URL}/web/session/authenticate",
json=auth_payload
)
uid = response.json()['result']['uid']
print(f"Authenticated as UID: {uid}")
Para XML-RPC, use a autenticação padrão em duas etapas:
import xmlrpc.client
url = "https://your-odoo.com"
db = "your_database"
username = "admin"
password = "your_password"
# Step 1: Get UID
common = xmlrpc.client.ServerProxy(f"{url}/xmlrpc/2/common")
uid = common.authenticate(db, username, password, {})
# Step 2: Use UID for subsequent calls
models = xmlrpc.client.ServerProxy(f"{url}/xmlrpc/2/object")
##API REST: OpenAPI 3.0
Odoo 19 apresenta uma API REST completa com especificação OpenAPI 3.0. Acesse a documentação interativa em https://your-odoo.com/api/docs.
Listagem de registros
# GET /api/sale.order — list all sales orders
response = requests.get(
f"{ODOO_URL}/api/sale.order",
headers=headers,
params={
"domain": '[["state", "=", "sale"]]',
"fields": '["name", "partner_id", "amount_total", "state"]',
"limit": 50,
"offset": 0
}
)
orders = response.json()
Lendo um único registro
# GET /api/sale.order/{id}
order_id = 123
response = requests.get(
f"{ODOO_URL}/api/sale.order/{order_id}",
headers=headers
)
order = response.json()
Criando um registro
# POST /api/sale.order
payload = {
"partner_id": 42,
"order_line": [
{
"product_id": 7,
"product_uom_qty": 5,
"price_unit": 100.0
}
]
}
response = requests.post(
f"{ODOO_URL}/api/sale.order",
headers=headers,
json=payload
)
new_order = response.json()
Atualizando um registro
# PATCH /api/sale.order/{id}
response = requests.patch(
f"{ODOO_URL}/api/sale.order/{order_id}",
headers=headers,
json={"note": "Rush order — priority handling required"}
)
Excluindo um registro
# DELETE /api/sale.order/{id}
response = requests.delete(
f"{ODOO_URL}/api/sale.order/{order_id}",
headers=headers
)
##Interface JSON-RPC
JSON-RPC fornece acesso à API Odoo Python completa, incluindo métodos do lado do servidor que não são expostos via REST. O endpoint primário é /web/dataset/call_kw.
Pesquisa e leitura básica
def call_kw(model, method, args, kwargs=None):
payload = {
"jsonrpc": "2.0",
"method": "call",
"params": {
"model": model,
"method": method,
"args": args,
"kwargs": kwargs or {}
}
}
response = session.post(
f"{ODOO_URL}/web/dataset/call_kw",
json=payload
)
return response.json().get('result')
# Search for confirmed sales orders
order_ids = call_kw(
"sale.order",
"search",
[[["state", "=", "sale"]]],
{"limit": 100, "order": "date_order desc"}
)
# Read specific fields
orders = call_kw(
"sale.order",
"read",
[order_ids],
{"fields": ["name", "partner_id", "amount_total", "date_order"]}
)
Leitura de pesquisa (combinada)
orders = call_kw(
"sale.order",
"search_read",
[[["partner_id.country_id.code", "=", "US"]]],
{
"fields": ["name", "partner_id", "amount_total"],
"limit": 50,
"offset": 0,
"order": "amount_total desc"
}
)
Criando Registros
new_id = call_kw(
"sale.order",
"create",
[{
"partner_id": 42,
"order_line": [
(0, 0, {
"product_id": 7,
"product_uom_qty": 10,
"price_unit": 150.0
})
]
}]
)
Chamando métodos do lado do servidor
JSON-RPC dá acesso a todos os métodos Python definidos nos modelos Odoo:
# Confirm a sales order (triggers workflow)
call_kw("sale.order", "action_confirm", [[order_id]])
# Validate an inventory transfer
call_kw("stock.picking", "button_validate", [[picking_id]])
# Get the action for a button (useful for understanding what a button does)
action = call_kw("sale.order", "action_quotations_with_onboarding", [[]])
Interface XML-RPC
XML-RPC é a API Odoo original e permanece totalmente suportada. A interface consiste em dois terminais:
/xmlrpc/2/common— métodos não autenticados (autenticar, versão)/xmlrpc/2/object— todas as operações do modelo (requer UID)
import xmlrpc.client
url = "https://your-odoo.com"
db, username, password = "mydb", "admin", "mypassword"
common = xmlrpc.client.ServerProxy(f"{url}/xmlrpc/2/common")
uid = common.authenticate(db, username, password, {})
models = xmlrpc.client.ServerProxy(f"{url}/xmlrpc/2/object")
# Search for products
product_ids = models.execute_kw(
db, uid, password,
'product.template', 'search',
[[['sale_ok', '=', True]]],
{'limit': 100}
)
# Read product data
products = models.execute_kw(
db, uid, password,
'product.template', 'read',
[product_ids],
{'fields': ['name', 'list_price', 'categ_id']}
)
# Create a new product
new_product_id = models.execute_kw(
db, uid, password,
'product.template', 'create',
[{
'name': 'My New Product',
'list_price': 99.99,
'type': 'consu'
}]
)
Filtros de Domínio
A sintaxe do filtro de domínio do Odoo é usada em todos os três tipos de API. Compreender os domínios é essencial para a recuperação eficiente de dados.
# Basic operators: =, !=, >, <, >=, <=, like, ilike, in, not in, child_of
domain = [
["state", "in", ["sale", "done"]], # Confirmed or done orders
["amount_total", ">=", 1000], # Total at least 1000
["partner_id.country_id.code", "=", "US"] # US customers (related field)
]
# Logical operators: & (AND, default), | (OR), ! (NOT)
domain = [
"|",
["state", "=", "draft"],
["state", "=", "cancel"]
]
# Complex: orders from US or UK customers with total > 5000
domain = [
"|",
["partner_id.country_id.code", "=", "US"],
["partner_id.country_id.code", "=", "GB"],
["amount_total", ">", 5000]
]
Webhooks e integração orientada a eventos
Odoo 19 oferece suporte a webhooks de saída acionados por alterações de registro. Configure webhooks em Configurações → Técnico → Webhooks.
Configuração do webhook:
- Navegue até Configurações → Técnico → Webhooks → Criar
- Defina o Modelo (por exemplo,
sale.order) - Selecione Trigger: criar, gravar, desvincular ou método personalizado
- Insira o URL do endpoint do seu serviço de recebimento
- Opcionalmente, defina Domínio para filtrar quais registros acionam o webhook
- Configure Campos para incluir na carga útil
Recebendo eventos de webhook em um serviço Flask:
from flask import Flask, request, jsonify
import hmac, hashlib
app = Flask(__name__)
WEBHOOK_SECRET = "your_webhook_secret"
@app.route("/odoo-webhook", methods=["POST"])
def handle_webhook():
# Verify signature
signature = request.headers.get("X-Odoo-Signature")
body = request.get_data()
expected = hmac.new(
WEBHOOK_SECRET.encode(),
body,
hashlib.sha256
).hexdigest()
if not hmac.compare_digest(signature, expected):
return jsonify({"error": "Invalid signature"}), 401
event = request.json
model = event.get("model")
record_id = event.get("id")
# Process the event
if model == "sale.order":
handle_order_event(record_id, event)
return jsonify({"status": "ok"}), 200
Tratamento de erros e lógica de nova tentativa
Integrações robustas devem lidar com erros da API Odoo normalmente.
import time
import requests
from requests.exceptions import RequestException
def api_call_with_retry(url, payload, headers, max_retries=3, backoff=2):
for attempt in range(max_retries):
try:
response = requests.post(url, json=payload, headers=headers, timeout=30)
response.raise_for_status()
data = response.json()
if "error" in data:
error = data["error"]
code = error.get("code", 0)
message = error.get("data", {}).get("message", "Unknown error")
# Don't retry validation errors
if code in [200, 100]:
raise ValueError(f"Odoo validation error: {message}")
raise RuntimeError(f"Odoo API error {code}: {message}")
return data.get("result")
except (RequestException, RuntimeError) as e:
if attempt == max_retries - 1:
raise
wait = backoff ** attempt
print(f"Attempt {attempt + 1} failed: {e}. Retrying in {wait}s...")
time.sleep(wait)
Códigos de erro comuns:
| Código | Significado | Ação |
|---|---|---|
| 100 | Erro no servidor | Verifique os registros do Odoo |
| 200 | Acesso negado | Verifique as permissões do usuário |
| 300 | Registro ausente | Verifique se o ID do registro existe |
| 304 | Campo obrigatório ausente | Revisar carga útil |
Práticas recomendadas de desempenho
Operações em lote: nunca chame a API em um loop para registros individuais. Use create_multi e write com listas:
# Bad: loop with individual creates
for product in products:
call_kw("product.template", "create", [product])
# Good: batch create
call_kw("product.template", "create", [products])
Seleção de campos: Sempre especifique o parâmetro fields para evitar a busca de todos os campos:
# Good: only fetch needed fields
orders = call_kw(
"sale.order", "search_read",
[[["state", "=", "sale"]]],
{"fields": ["name", "amount_total"], "limit": 1000}
)
Paginação: para grandes conjuntos de dados, paginar usando limit e offset:
def fetch_all_records(model, domain, fields, batch_size=500):
records = []
offset = 0
while True:
batch = call_kw(
model, "search_read", [domain],
{"fields": fields, "limit": batch_size, "offset": offset}
)
records.extend(batch)
if len(batch) < batch_size:
break
offset += batch_size
return records
Perguntas frequentes
Qual é a diferença entre JSON-RPC e a API REST no Odoo 19?
JSON-RPC fornece acesso à API Odoo Python completa, incluindo todos os métodos do lado do servidor, enquanto REST segue as convenções OpenAPI 3.0 e expõe uma interface mais limitada, mas padronizada. Para novas integrações em que REST cobre seu caso de uso, REST é preferido por sua capacidade de descoberta. Para automação de fluxo de trabalho complexo ou acesso a métodos Python personalizados, use JSON-RPC.
Como lidar com grandes exportações de dados (mais de 100 mil registros) de maneira eficiente?
Use paginação com search_read e um tamanho de lote de 500 a 1.000 registros. Para exportações muito grandes, considere usar o recurso de exportação do Odoo por meio da interface do usuário para extrações únicas ou agende trabalhos em segundo plano usando o modelo ir.cron do Odoo para processar dados em partes fora dos horários de pico, em vez de fazer chamadas de API em tempo real.
Posso usar chaves de API em vez de nome de usuário/senha para XML-RPC?
Sim. No Odoo 13+, as chaves de API podem ser usadas como senhas na chamada de autenticação XML-RPC. Gere uma chave API a partir do seu perfil de usuário e use-a no lugar da sua senha: common.authenticate(db, username, api_key, {}). Esta é a abordagem recomendada para contas de serviço.
Como crio registros Many2many e One2many por meio da API?
Use as tuplas de comando do Odoo: (0, 0, vals) cria um novo registro relacionado, (1, id, vals) atualiza um registro relacionado existente, (2, id, 0) exclui um registro relacionado, (4, id, 0) vincula um registro existente, (5, 0, 0) desvincula todos os registros relacionados. Esses comandos funcionam de forma idêntica em JSON-RPC, XML-RPC e REST.
Como acionar uma ação de fluxo de trabalho (como confirmar um pedido) por meio da API?
Chame o método correspondente no modelo. Para confirmar um pedido de venda, ligue para action_confirm em sale.order. Para validar uma entrega, ligue para button_validate em stock.picking. Esses métodos são visíveis no código-fonte do Odoo e podem ser descobertos inspecionando o atributo name do botão no modo de desenvolvedor da UI.
Quais limites de taxa o Odoo impõe às chamadas de API?
Odoo não impõe limites de taxa de API nativamente no nível do aplicativo. A limitação de taxa deve ser configurada no proxy reverso (Nginx) ou no nível da infraestrutura. Um padrão sensato é 60 solicitações por minuto por IP para integrações externas. Para integrações de alto rendimento, use uma abordagem baseada em fila com um usuário de serviço dedicado.
Próximas etapas
Construir uma integração confiável da API Odoo requer mais do que exemplos de código funcionais – exige tratamento adequado de erros, monitoramento, gerenciamento de credenciais e alinhamento com o modelo de dados do Odoo.
A equipe de integração da ECOSIRE construiu conexões de nível de produção entre Odoo e dezenas de plataformas, incluindo Shopify, Amazon, GoHighLevel, Power BI, ERPs personalizados e sistemas proprietários. Lidamos com arquitetura de autenticação, design de webhook, transformação de dados e monitoramento contínuo.
Fale com ECOSIRE sobre seu projeto de integração Odoo →
Esteja você iniciando uma nova integração ou consertando uma que não funciona, nossos engenheiros analisarão seus requisitos e fornecerão uma solução que lide com casos extremos desde o primeiro dia.
Escrito por
ECOSIRE Research and Development Team
Construindo produtos digitais de nível empresarial na ECOSIRE. Compartilhando insights sobre integrações Odoo, automação de e-commerce e soluções de negócios com IA.
Artigos Relacionados
Odoo Accounting vs QuickBooks: Detailed Comparison 2026
In-depth 2026 comparison of Odoo Accounting vs QuickBooks covering features, pricing, integrations, scalability, and which platform fits your business needs.
AI + ERP Integration: How AI is Transforming Enterprise Resource Planning
Learn how AI is transforming ERP systems in 2026—from intelligent automation and predictive analytics to natural language interfaces and autonomous operations.
All-in-One vs Best-of-Breed: The Software Stack Decision
All-in-one vs best-of-breed software strategy for 2026: integration complexity, total cost, vendor risk, and when each approach is right for your business.