Odoo API Integration: REST, JSON-RPC, and XML-RPC Guide

Complete developer guide to Odoo API integration using REST, JSON-RPC, and XML-RPC. Includes authentication, endpoints, code examples, and best practices.

E
ECOSIRE Research and Development Team
|19 de março de 202610 min de leitura2.3k Palavras|

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:

RecursoAPI RESTJSON-RPCXML-RPC
ProtocoloHTTP/HTTPSHTTP/HTTPSHTTP/HTTPS
Formato de carga útilJSONJSONXML
Especificação OpenAPISim (arrogância)NãoNão
Operações CRUDSimSimSim
Chamadas de métodoLimitadoCompletoCompleto
Gatilhos de fluxo de trabalhoAtravés de açõesAtravés de execute_kwAtravés de executar
Recomendado paraNovas integraçõesLógica complexaSistemas legados
Biblioteca Pythonpedidosodoo-xmlrpc/solicitaçõesxmlrpc.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:

  1. Navegue até Configurações → Técnico → Webhooks → Criar
  2. Defina o Modelo (por exemplo, sale.order)
  3. Selecione Trigger: criar, gravar, desvincular ou método personalizado
  4. Insira o URL do endpoint do seu serviço de recebimento
  5. Opcionalmente, defina Domínio para filtrar quais registros acionam o webhook
  6. 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ódigoSignificadoAção
100Erro no servidorVerifique os registros do Odoo
200Acesso negadoVerifique as permissões do usuário
300Registro ausenteVerifique se o ID do registro existe
304Campo obrigatório ausenteRevisar 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.

Compartilhar:
E

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.

Converse no WhatsApp