Odoo API 集成:REST、JSON-RPC 和 XML-RPC 指南
Odoo 19 公开了三个 API 接口,涵盖从简单的数据检索到复杂的工作流程自动化的所有内容。无论您是构建自定义移动应用程序、与第三方平台同步,还是通过外部微服务扩展 Odoo 的功能,掌握 Odoo API 层都是任何重要集成项目的基础。
本指南提供了适用于 REST、JSON-RPC 和 XML-RPC 集成(Odoo 19 Enterprise 中提供的三个主要接口)的工作代码示例、身份验证流程和架构建议。
要点
- Odoo 19 提供 REST (OpenAPI 3.0)、JSON-RPC 2.0 和 XML-RPC 接口
- 身份验证使用 API 密钥(推荐)或基于会话的登录
- JSON-RPC是功能最齐全的复杂操作接口
- REST API 遵循 OpenAPI 3.0 规范并支持标准 HTTP 动词
- XML-RPC 是遗留的,但仍然完全支持向后兼容
- 速率限制和错误处理必须在客户端实现
- Odoo 19 中的 Webhook 将记录更改的数据推送到外部系统
- 所有 API 调用均尊重 Odoo 的访问权限和记录规则
API接口对比
在编写一行代码之前,请为您的用例选择正确的 API 接口:
| 特色 | 休息 API | JSON-RPC | XML-RPC |
|---|---|---|---|
| 协议 | HTTP/HTTPS | HTTP/HTTPS | HTTP/HTTPS |
| 有效负载格式 | JSON | JSON | XML |
| OpenAPI 规范 | 是的(大摇大摆) | 没有 | 没有 |
| CRUD 操作 | 是的 | 是的 | 是的 |
| 方法调用 | 有限公司 | 完整 | 完整 |
| 工作流程触发器 | 通过行动 | 通过execute_kw | 通过执行 |
| 推荐用于 | 新的集成 | 复杂逻辑 | 遗留系统 |
| Python 库 | 请求 | odoo-xmlrpc / 请求 | xmlrpc.client |
何时使用 REST:构建移动应用程序、与 webhook 本机平台(Shopify、Stripe)集成,或者当您的团队更熟悉 REST 约定时。
何时使用 JSON-RPC:执行复杂的 Odoo 服务器端方法、使用域过滤器读取大型数据集,或者当您需要访问未通过 REST 公开的方法时。
何时使用 XML-RPC:维护在 REST 可用之前构建的现有集成,或者当您的平台具有成熟的 XML-RPC 客户端库时。
身份验证
API密钥认证(推荐)
Odoo 19 支持所有三个接口的 API 密钥身份验证。在 设置 → 用户 → 您的用户 → API 密钥 下生成 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}"
}
API 密钥的范围仅限于特定用户并继承该用户的访问权限。创建具有集成帐户所需的最低权限的专用服务用户。
基于会话的身份验证(JSON-RPC / XML-RPC)
对于 JSON-RPC,在建立会话后使用 /web/dataset/call_kw 端点进行身份验证:
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}")
对于 XML-RPC,使用标准的两步身份验证:
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")
REST API:OpenAPI 3.0
Odoo 19 引入了符合 OpenAPI 3.0 规范的完整 REST API。访问 https://your-odoo.com/api/docs 处的交互式文档。
列出记录
# 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()
读取单个记录
# GET /api/sale.order/{id}
order_id = 123
response = requests.get(
f"{ODOO_URL}/api/sale.order/{order_id}",
headers=headers
)
order = response.json()
创建记录
# 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()
更新记录
# 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"}
)
删除记录
# DELETE /api/sale.order/{id}
response = requests.delete(
f"{ODOO_URL}/api/sale.order/{order_id}",
headers=headers
)
JSON-RPC 接口
JSON-RPC 提供对完整 Odoo Python API 的访问,包括不通过 REST 公开的服务器端方法。主要终点是 /web/dataset/call_kw。
基本搜索和阅读
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"]}
)
搜索阅读(合并)
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"
}
)
创建记录
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
})
]
}]
)
调用服务器端方法
JSON-RPC 允许访问 Odoo 模型上定义的所有 Python 方法:
# 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", [[]])
XML-RPC 接口
XML-RPC 是原始的 Odoo API,并且仍然得到完全支持。该接口由两个端点组成:
/xmlrpc/2/common— 未经身份验证的方法(身份验证、版本)/xmlrpc/2/object— 所有模型操作(需要 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'
}]
)
域过滤器
Odoo 的域过滤器语法适用于所有三种 API 类型。了解域对于有效的数据检索至关重要。
# 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]
]
Webhook 和事件驱动集成
Odoo 19 支持由记录更改触发的出站 Webhook。在 设置 → 技术 → Webhooks 下配置 Webhooks。
网络钩子配置:
- 导航至 设置 → 技术 → Webhooks → 创建
- 设置 型号(例如
sale.order) - 选择触发器:创建、写入、取消链接或自定义方法
- 输入接收服务的 端点 URL
- (可选)设置 Domain 来过滤哪些记录触发 webhook
- 配置 Fields 以包含在有效负载中
在 Flask 服务中接收 webhook 事件:
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
错误处理和重试逻辑
强大的集成必须妥善处理 Odoo API 错误。
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)
常见错误代码:
| 代码 | 意义 | 行动 |
|---|---|---|
| 100 | 100服务器错误 | 检查 Odoo 日志 |
| 200 | 200访问被拒绝 | 验证用户权限 |
| 300 | 300失踪记录 | 检查记录ID是否存在 |
| 304 | 304缺少必填字段 | 审查有效负载 |
性能最佳实践
批量操作:切勿在循环中为单个记录调用 API。将 create_multi 和 write 与列表一起使用:
# Bad: loop with individual creates
for product in products:
call_kw("product.template", "create", [product])
# Good: batch create
call_kw("product.template", "create", [products])
字段选择:始终指定 fields 参数以避免获取所有字段:
# Good: only fetch needed fields
orders = call_kw(
"sale.order", "search_read",
[[["state", "=", "sale"]]],
{"fields": ["name", "amount_total"], "limit": 1000}
)
分页:对于大型数据集,使用 limit 和 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
常见问题
Odoo 19 中 JSON-RPC 和 REST API 有什么区别?
JSON-RPC 提供对完整 Odoo Python API 的访问,包括所有服务器端方法,而 REST 遵循 OpenAPI 3.0 约定并公开更有限但标准化的接口。对于 REST 涵盖您的用例的新集成,REST 因其可发现性而成为首选。对于复杂的工作流程自动化或访问自定义 Python 方法,请使用 JSON-RPC。
如何高效处理大数据导出(10万+条记录)?
使用带有 search_read 的分页和 500–1000 条记录的批量大小。对于非常大的导出,请考虑通过 UI 使用 Odoo 的导出功能进行一次性提取,或者使用 Odoo 的 ir.cron 模型安排后台作业,以便在非高峰时段处理大块数据,而不是进行实时 API 调用。
我可以使用 API 密钥代替 XML-RPC 的用户名/密码吗?
是的。在 Odoo 13+ 中,API 密钥可以用作 XML-RPC 身份验证调用中的密码。从您的用户配置文件生成 API 密钥并使用它代替您的密码:common.authenticate(db, username, api_key, {})。这是服务帐户的推荐方法。
如何通过 API 创建 Many2many 和 One2many 记录?
使用 Odoo 的命令元组: (0, 0, vals) 创建新的相关记录, (1, id, vals) 更新现有的相关记录, (2, id, 0) 删除相关记录, (4, id, 0) 链接现有记录, (5, 0, 0) 取消链接所有相关记录。这些命令在 JSON-RPC、XML-RPC 和 REST 中的工作方式相同。
如何通过 API 触发工作流程操作(例如确认订单)?
调用模型上相应的方法。要确认销售订单,请致电 sale.order 上的 action_confirm。要验证交货,请致电 stock.picking 上的 button_validate。这些方法在 Odoo 的源代码中可见,并且可以通过在 UI 开发者模式中检查按钮的 name 属性来发现。
Odoo 对 API 调用施加什么速率限制?
Odoo 本身并不在应用程序级别强制执行 API 速率限制。必须在反向代理 (Nginx) 或基础设施级别配置速率限制。对于外部集成,合理的默认值是每个 IP 每分钟 60 个请求。对于高吞吐量集成,请使用基于队列的方法和专门的服务用户。
后续步骤
构建可靠的 Odoo API 集成需要的不仅仅是工作代码示例 - 它还需要正确的错误处理、监控、凭证管理以及与 Odoo 数据模型的一致性。
ECOSIRE 的集成团队已在 Odoo 与数十个平台(包括 Shopify、Amazon、GoHighLevel、Power BI、自定义 ERP 和专有系统)之间建立了生产级连接。我们处理身份验证架构、Webhook 设计、数据转换和持续监控。
无论您是开始新的集成还是修复损坏的集成,我们的工程师都会审查您的需求,并从第一天起就提供处理边缘情况的解决方案。
作者
ECOSIRE TeamTechnical Writing
The ECOSIRE technical writing team covers Odoo ERP, Shopify eCommerce, AI agents, Power BI analytics, GoHighLevel automation, and enterprise software best practices. Our guides help businesses make informed technology decisions.
相关文章
AI 支持的客户细分:从 RFM 到预测聚类
了解 AI 如何将客户细分从静态 RFM 分析转变为动态预测聚类。使用 Python、Odoo 和真实 ROI 数据的实施指南。
用于供应链优化的人工智能:可见性、预测和自动化
利用人工智能改变供应链运营:需求感知、供应商风险评分、路线优化、仓库自动化和中断预测。 2026年指南。
B2B电子商务战略:2026年打造在线批发业务
通过批发定价、帐户管理、信用条款、打孔目录和 Odoo B2B 门户配置策略来掌握 B2B 电子商务。