Odoo API 統合: REST、JSON-RPC、および XML-RPC ガイド
Odoo 19 は、単純なデータ取得から複雑なワークフローの自動化まですべてをカバーする 3 つの API インターフェイスを公開します。カスタム モバイル アプリを構築する場合でも、サードパーティ プラットフォームと同期する場合でも、外部マイクロサービスを使用して Odoo の機能を拡張する場合でも、Odoo API レイヤーをマスターすることは、本格的な統合プロジェクトの基礎となります。
このガイドでは、Odoo 19 Enterprise で利用できる 3 つの主要なインターフェイスである REST、JSON-RPC、および XML-RPC の統合に関する実際のコード例、認証フロー、アーキテクチャの推奨事項を説明します。
重要なポイント
- 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 インターフェースの比較
コードを 1 行記述する前に、ユースケースに適した API インターフェイスを選択してください。
| 特集 | REST API | JSON-RPC | XML-RPC |
|---|---|---|---|
| プロトコル | HTTP/HTTPS | HTTP/HTTPS | HTTP/HTTPS |
| ペイロード形式 | JSON | JSON | XML |
| OpenAPI 仕様 | はい (スワッガー) | いいえ | いいえ |
| CRUD 操作 | はい | はい | はい |
| メソッド呼び出し | 限定 | フル | フル |
| ワークフロートリガー | アクション経由 | 実行_kw経由 | 実行経由 |
| こんな人におすすめ | 新しい統合 | 複雑なロジック | レガシー システム |
| Pythonライブラリ | リクエスト | odoo-xmlrpc / リクエスト | xmlrpc.client |
REST を使用する場合: モバイル アプリを構築する場合、Webhook ネイティブ プラットフォーム (Shopify、Stripe) と統合する場合、またはチームが REST 規約に慣れている場合。
JSON-RPC を使用する場合: 複雑な Odoo サーバー側メソッドの実行、ドメイン フィルターを使用した大規模なデータセットの読み取り、または REST 経由で公開されていないメソッドへのアクセスが必要な場合。
XML-RPC を使用する場合: REST が利用可能になる前に構築された既存の統合を維持する場合、またはプラットフォームに成熟した XML-RPC クライアント ライブラリがある場合。
認証
API キー認証 (推奨)
Odoo 19 は、3 つのインターフェイスすべての 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 の場合は、標準の 2 段階認証を使用します。
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 は、REST 経由で公開されないサーバー側のメソッドを含む、完全な Odoo Python API へのアクセスを提供します。プライマリエンドポイントは /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 であり、引き続き完全にサポートされています。インターフェイスは 2 つのエンドポイントで構成されます。
/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 のドメイン フィルター構文は、3 つの 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 をサポートします。 [設定] → [テクニカル] → [Webhook] で Webhook を構成します。
Webhook 設定:
- [設定] → [技術] → [Webhook] → [作成] に移動します。
- モデル (例:
sale.order) を設定します。 - トリガーを選択します: 作成、書き込み、リンク解除、またはカスタム メソッド
- 受信サービスの エンドポイント URL を入力します
- 必要に応じて、Webhook をトリガーするレコードをフィルターするように ドメイン を設定します。
- フィールドを構成してペイロードに含めます
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 | サーバーエラー | Odoo ログを確認する |
| 200 | アクセスが拒否されました | ユーザー権限を確認する |
| 300 | 記録がありません | レコード ID が存在することを確認してください |
| 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 を使用します。
大規模なデータのエクスポート (100k 以上のレコード) を効率的に処理するにはどうすればよいですか?
search_read と 500 ~ 1000 レコードのバッチ サイズでページネーションを使用します。非常に大規模なエクスポートの場合は、UI を介して Odoo のエクスポート機能を使用して 1 回限りの抽出を行うことを検討するか、Odoo の ir.cron モデルを使用してバックグラウンド ジョブをスケジュールして、リアルタイムの API 呼び出しを行うのではなく、オフピーク時にデータをまとめて処理します。
XML-RPC のユーザー名/パスワードの代わりに API キーを使用できますか?
はい。 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 ごとに 1 分あたり 60 リクエストです。高スループットの統合の場合は、専用のサービス ユーザーによるキューベースのアプローチを使用します。
次のステップ
信頼性の高い Odoo API 統合を構築するには、機能するコード サンプル以上のものが必要です。適切なエラー処理、監視、認証情報の管理、Odoo のデータ モデルとの調整が必要です。
ECOSIRE の統合チームは、Odoo と、Shopify、Amazon、GoHighLevel、Power BI、カスタム ERP、独自システムなどの数十のプラットフォームとの間に実稼働グレードの接続を構築しました。当社は、認証アーキテクチャ、Webhook 設計、データ変換、継続的な監視を扱います。
Odoo 統合プロジェクトについて ECOSIRE にご相談ください →
新しい統合を開始する場合でも、壊れた統合を修正する場合でも、当社のエンジニアが要件を検討し、初日からエッジケースに対応するソリューションを提供します。
執筆者
ECOSIRE Research and Development Team
ECOSIREでエンタープライズグレードのデジタル製品を開発。Odoo統合、eコマース自動化、AI搭載ビジネスソリューションに関するインサイトを共有しています。
関連記事
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.