Odoo API-Integration: REST-, JSON-RPC- und XML-RPC-Leitfaden
Odoo 19 stellt drei API-Schnittstellen zur Verfügung, die alles vom einfachen Datenabruf bis hin zur komplexen Workflow-Automatisierung abdecken. Unabhängig davon, ob Sie eine benutzerdefinierte mobile App erstellen, mit einer Plattform eines Drittanbieters synchronisieren oder die Funktionen von Odoo mit externen Microservices erweitern, ist die Beherrschung der Odoo-API-Ebene für jedes ernsthafte Integrationsprojekt von grundlegender Bedeutung.
Dieser Leitfaden bietet funktionierende Codebeispiele, Authentifizierungsabläufe und Architekturempfehlungen für REST-, JSON-RPC- und XML-RPC-Integrationen – die drei primären Schnittstellen, die in Odoo 19 Enterprise verfügbar sind.
Wichtige Erkenntnisse
- Odoo 19 bietet REST- (OpenAPI 3.0), JSON-RPC 2.0- und XML-RPC-Schnittstellen – Die Authentifizierung erfolgt über API-Schlüssel (empfohlen) oder eine sitzungsbasierte Anmeldung
- JSON-RPC ist die Schnittstelle mit dem umfassendsten Funktionsumfang für komplexe Vorgänge – Die REST-API folgt der OpenAPI 3.0-Spezifikation und unterstützt Standard-HTTP-Verben
- XML-RPC ist veraltet, wird aber aus Gründen der Abwärtskompatibilität immer noch vollständig unterstützt
- Ratenbegrenzung und Fehlerbehandlung müssen auf der Clientseite implementiert werden
- Webhooks in Odoo 19 übertragen Daten bei Datensatzänderungen an externe Systeme
- Alle API-Aufrufe respektieren die Zugriffsrechte und Aufzeichnungsregeln von Odoo
Vergleich der API-Schnittstelle
Bevor Sie eine einzelne Codezeile schreiben, wählen Sie die richtige API-Schnittstelle für Ihren Anwendungsfall:
| Funktion | REST-API | JSON-RPC | XML-RPC |
|---|---|---|---|
| Protokoll | HTTP/HTTPS | HTTP/HTTPS | HTTP/HTTPS |
| Nutzlastformat | JSON | JSON | XML |
| OpenAPI-Spezifikation | Ja (Swagger) | Nein | Nein |
| CRUD-Operationen | Ja | Ja | Ja |
| Methodenaufrufe | Begrenzt | Voll | Voll |
| Workflow-Trigger | Über Aktionen | Überexecute_kw | Über Ausführen |
| Empfohlen für | Neue Integrationen | Komplexe Logik | Legacy-Systeme |
| Python-Bibliothek | Anfragen | odoo-xmlrpc / Anfragen | xmlrpc.client |
Wann sollte REST verwendet werden?: Erstellen einer mobilen App, Integration mit Webhook-nativen Plattformen (Shopify, Stripe) oder wenn Ihr Team mit REST-Konventionen besser vertraut ist.
Wann sollte JSON-RPC verwendet werden?: Ausführen komplexer serverseitiger Odoo-Methoden, Lesen großer Datensätze mit Domänenfiltern oder wenn Sie Zugriff auf Methoden benötigen, die nicht über REST verfügbar gemacht werden.
Wann XML-RPC verwendet werden sollte: Beibehaltung vorhandener Integrationen, die vor der Verfügbarkeit von REST erstellt wurden, oder wenn Ihre Plattform über ausgereifte XML-RPC-Clientbibliotheken verfügt.
Authentifizierung
API-Schlüsselauthentifizierung (empfohlen)
Odoo 19 unterstützt die API-Schlüsselauthentifizierung für alle drei Schnittstellen. Generieren Sie einen API-Schlüssel unter Einstellungen → Benutzer → Ihr Benutzer → API-Schlüssel.
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-Schlüssel sind auf einen bestimmten Benutzer beschränkt und erben die Zugriffsrechte dieses Benutzers. Erstellen Sie dedizierte Dienstbenutzer mit den minimal erforderlichen Berechtigungen für Integrationskonten.
Sitzungsbasierte Authentifizierung (JSON-RPC / XML-RPC)
Für JSON-RPC authentifizieren Sie sich nach dem Einrichten einer Sitzung mithilfe des Endpunkts /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}")
Verwenden Sie für XML-RPC die standardmäßige zweistufige Authentifizierung:
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 führt eine vollständige REST-API mit der OpenAPI 3.0-Spezifikation ein. Greifen Sie auf die interaktive Dokumentation unter https://your-odoo.com/api/docs zu.
Datensätze auflisten
# 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()
Einen einzelnen Datensatz lesen
# GET /api/sale.order/{id}
order_id = 123
response = requests.get(
f"{ODOO_URL}/api/sale.order/{order_id}",
headers=headers
)
order = response.json()
Erstellen eines Datensatzes
# 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()
Einen Datensatz aktualisieren
# 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"}
)
Einen Datensatz löschen
# DELETE /api/sale.order/{id}
response = requests.delete(
f"{ODOO_URL}/api/sale.order/{order_id}",
headers=headers
)
JSON-RPC-Schnittstelle
JSON-RPC bietet Zugriff auf die vollständige Odoo-Python-API, einschließlich serverseitiger Methoden, die nicht über REST verfügbar gemacht werden. Der primäre Endpunkt ist /web/dataset/call_kw.
Einfaches Suchen und Lesen
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"]}
)
Suche lesen (kombiniert)
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"
}
)
Datensätze erstellen
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
})
]
}]
)
Serverseitige Methoden aufrufen
JSON-RPC ermöglicht den Zugriff auf alle in Odoo-Modellen definierten Python-Methoden:
# 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-Schnittstelle
XML-RPC ist die ursprüngliche Odoo-API und wird weiterhin vollständig unterstützt. Die Schnittstelle besteht aus zwei Endpunkten:
/xmlrpc/2/common– nicht authentifizierte Methoden (authentifizieren, Version)/xmlrpc/2/object– alle Modelloperationen (erfordert 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'
}]
)
Domänenfilter
Die Domänenfiltersyntax von Odoo wird für alle drei API-Typen verwendet. Für einen effizienten Datenabruf ist das Verständnis von Domänen unerlässlich.
# 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 und ereignisgesteuerte Integration
Odoo 19 unterstützt ausgehende Webhooks, die durch Datensatzänderungen ausgelöst werden. Konfigurieren Sie Webhooks unter Einstellungen → Technik → Webhooks.
Webhook-Konfiguration:
- Navigieren Sie zu Einstellungen → Technik → Webhooks → Erstellen
- Legen Sie das Modell fest (z. B.
sale.order) - Wählen Sie Trigger: Erstellen, Schreiben, Verknüpfung aufheben oder benutzerdefinierte Methode
- Geben Sie die Endpunkt-URL Ihres Empfangsdienstes ein
- Legen Sie optional Domäne fest, um zu filtern, welche Datensätze den Webhook auslösen
- Konfigurieren Sie Felder, um sie in die Nutzlast aufzunehmen
Empfangen von Webhook-Ereignissen in einem Flask-Dienst:
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
Fehlerbehandlung und Wiederholungslogik
Robuste Integrationen müssen Odoo-API-Fehler ordnungsgemäß verarbeiten.
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)
Häufige Fehlercodes:
| Code | Bedeutung | Aktion |
|---|---|---|
| 100 | Serverfehler | Überprüfen Sie die Odoo-Protokolle |
| 200 | Zugriff verweigert | Benutzerberechtigungen überprüfen |
| 300 | Fehlender Datensatz | Überprüfen Sie, ob die Datensatz-ID vorhanden ist |
| 304 | Fehlendes Pflichtfeld | Nutzlast überprüfen |
Best Practices für die Leistung
Stapeloperationen: Rufen Sie die API niemals in einer Schleife für einzelne Datensätze auf. Verwenden Sie create_multi und write mit Listen:
# Bad: loop with individual creates
for product in products:
call_kw("product.template", "create", [product])
# Good: batch create
call_kw("product.template", "create", [products])
Feldauswahl: Geben Sie immer den Parameter fields an, um zu vermeiden, dass alle Felder abgerufen werden:
# Good: only fetch needed fields
orders = call_kw(
"sale.order", "search_read",
[[["state", "=", "sale"]]],
{"fields": ["name", "amount_total"], "limit": 1000}
)
Paginierung: Paginieren Sie bei großen Datensätzen mit limit und 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
Häufig gestellte Fragen
Was ist der Unterschied zwischen JSON-RPC und der REST-API in Odoo 19?
JSON-RPC bietet Zugriff auf die vollständige Odoo-Python-API einschließlich aller serverseitigen Methoden, während REST den OpenAPI 3.0-Konventionen folgt und eine eingeschränktere, aber standardisierte Schnittstelle bereitstellt. Bei neuen Integrationen, bei denen REST Ihren Anwendungsfall abdeckt, wird REST aufgrund seiner Auffindbarkeit bevorzugt. Für die Automatisierung komplexer Arbeitsabläufe oder den Zugriff auf benutzerdefinierte Python-Methoden verwenden Sie JSON-RPC.
Wie gehe ich mit großen Datenexporten (mehr als 100.000 Datensätze) effizient um?
Verwenden Sie die Paginierung mit search_read und einer Stapelgröße von 500–1000 Datensätzen. Erwägen Sie bei sehr großen Exporten die Verwendung der Exportfunktion von Odoo über die Benutzeroberfläche für einmalige Extraktionen oder planen Sie Hintergrundjobs mithilfe des ir.cron-Modells von Odoo, um Daten außerhalb der Hauptverkehrszeiten in Blöcken zu verarbeiten, anstatt API-Aufrufe in Echtzeit durchzuführen.
Kann ich API-Schlüssel anstelle von Benutzername/Passwort für XML-RPC verwenden?
Ja. In Odoo 13+ können API-Schlüssel als Passwörter im XML-RPC-Authentifizierungsaufruf verwendet werden. Generieren Sie einen API-Schlüssel aus Ihrem Benutzerprofil und verwenden Sie ihn anstelle Ihres Passworts: common.authenticate(db, username, api_key, {}). Dies ist der empfohlene Ansatz für Dienstkonten.
Wie erstelle ich Many2many- und One2many-Datensätze über die API?
Verwenden Sie die Befehlstupel von Odoo: (0, 0, vals) erstellt einen neuen zugehörigen Datensatz, (1, id, vals) aktualisiert einen vorhandenen zugehörigen Datensatz, (2, id, 0) löscht einen zugehörigen Datensatz, (4, id, 0) verknüpft einen vorhandenen Datensatz, (5, 0, 0) hebt die Verknüpfung aller zugehörigen Datensätze auf. Diese Befehle funktionieren bei JSON-RPC, XML-RPC und REST identisch.
Wie löse ich eine Workflow-Aktion (z. B. die Bestätigung einer Bestellung) über die API aus?
Rufen Sie die entsprechende Methode für das Modell auf. Um einen Kundenauftrag zu bestätigen, rufen Sie action_confirm unter sale.order an. Um eine Lieferung zu validieren, rufen Sie button_validate unter stock.picking an. Diese Methoden sind im Quellcode von Odoo sichtbar und können durch Überprüfen des name-Attributs der Schaltfläche im Entwicklermodus der Benutzeroberfläche entdeckt werden.
Welche Ratenbeschränkungen legt Odoo für API-Aufrufe fest?
Odoo erzwingt API-Ratenbegrenzungen nicht nativ auf Anwendungsebene. Die Ratenbegrenzung muss auf Reverse-Proxy- (Nginx) oder Infrastrukturebene konfiguriert werden. Ein sinnvoller Standardwert sind 60 Anfragen pro Minute und IP für externe Integrationen. Verwenden Sie für Integrationen mit hohem Durchsatz einen warteschlangenbasierten Ansatz mit einem dedizierten Dienstbenutzer.
Nächste Schritte
Der Aufbau einer zuverlässigen Odoo-API-Integration erfordert mehr als funktionierende Codebeispiele – er erfordert eine ordnungsgemäße Fehlerbehandlung, Überwachung, Anmeldeinformationsverwaltung und Ausrichtung auf das Datenmodell von Odoo.
Das Integrationsteam von ECOSIRE hat produktionstaugliche Verbindungen zwischen Odoo und Dutzenden von Plattformen aufgebaut, darunter Shopify, Amazon, GoHighLevel, Power BI, benutzerdefinierte ERPs und proprietäre Systeme. Wir kümmern uns um die Authentifizierungsarchitektur, das Webhook-Design, die Datentransformation und die laufende Überwachung.
Sprechen Sie mit ECOSIRE über Ihr Odoo-Integrationsprojekt →
Ganz gleich, ob Sie mit einer neuen Integration beginnen oder eine defekte Integration reparieren, unsere Ingenieure prüfen Ihre Anforderungen und liefern eine Lösung, die Grenzfälle vom ersten Tag an bewältigt.
Geschrieben von
ECOSIRE Research and Development Team
Entwicklung von Enterprise-Digitalprodukten bei ECOSIRE. Einblicke in Odoo-Integrationen, E-Commerce-Automatisierung und KI-gestützte Geschäftslösungen.
Verwandte Artikel
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.