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
|2026年3月19日7 分で読める1.4k 語数|

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 APIJSON-RPCXML-RPC
プロトコルHTTP/HTTPSHTTP/HTTPSHTTP/HTTPS
ペイロード形式JSONJSONXML
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 設定:

  1. [設定] → [技術] → [Webhook] → [作成] に移動します。
  2. モデル (例: sale.order) を設定します。
  3. トリガーを選択します: 作成、書き込み、リンク解除、またはカスタム メソッド
  4. 受信サービスの エンドポイント URL を入力します
  5. 必要に応じて、Webhook をトリガーするレコードをフィルターするように ドメイン を設定します。
  6. フィールドを構成してペイロードに含めます

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_multiwrite を使用します。

# 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}
)

ページネーション: 大規模なデータセットの場合は、limitoffset を使用してページネーションします。

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.orderaction_confirm を呼び出します。配信を検証するには、stock.pickingbutton_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 にご相談ください →

新しい統合を開始する場合でも、壊れた統合を修正する場合でも、当社のエンジニアが要件を検討し、初日からエッジケースに対応するソリューションを提供します。

E

執筆者

ECOSIRE Research and Development Team

ECOSIREでエンタープライズグレードのデジタル製品を開発。Odoo統合、eコマース自動化、AI搭載ビジネスソリューションに関するインサイトを共有しています。

WhatsAppでチャット