Drivethru Odoo

Data & APIs

Talk to an Odoo ERP through its `agent_api` REST module — look up eBay products and inventory, push eBay sale orders and read tracking, run the Accounts Payable PO→vendor-bill flow, and schedule MRP production batches onto workcenters. Use whenever the user needs to read from or write to Odoo for eBay fulfillment, vendor-bill matching, or production planning.

Install

openclaw skills install drivethru-odoo

Odoo agent_api integration

This skill is a thin, JSON-in / JSON-out wrapper over the Odoo agent_api REST module (/agent_api/v1/*). It authenticates with the X-Agent-API-Key header and covers three domains, one CLI script each:

ScriptDomainOdoo endpoint prefix
scripts/sales.pyeBay sales/inventory/agent_api/v1/ebay/...
scripts/ap.pyAccounts Payable/agent_api/v1/ap/...
scripts/production.pyMRP scheduling/agent_api/v1/production/...

All three follow the same calling convention:

echo '<json-args>' | python3 scripts/<script>.py <action>

The action is the first CLI argument; arguments are a JSON object on stdin. Every script prints a single JSON object on stdout, or {"error": {"type": ..., "message": ...}} with a non-zero exit code on failure.

Required credentials

The agent host MUST expose ODOO_URL and ODOO_API_KEY in the environment before this skill is invoked. If either is missing, the scripts exit with {"error": {"type": "config_error", ...}} (exit code 2) — stop and tell the user to set them. Do not prompt the user to paste the key into chat; secrets come from the environment.

Set ODOO_DRY_RUN=true to preview writes without mutating Odoo.

When to use

  • "What eBay products / inventory do we have in Odoo?"
  • "Push this eBay order into Odoo" / "Is order X shipped — what's the tracking?"
  • "Find the PO for vendor X" / "Create the vendor bill for PO 123"
  • "Show me the production plan" / "Schedule batch 142 onto Manual Press A"

When NOT to use

  • Generic Odoo XML-RPC / ORM access — this skill only speaks the curated agent_api REST surface, not arbitrary models.
  • Editing products, posting bills, or confirming MOs outside the documented actions — do that in the Odoo UI or extend the agent_api addon.

Sales — scripts/sales.py

ActionInput (stdin JSON)Notes
list-products(none)Products in the Odoo 'eBay' category.
inventory{"skus": ["A-1", "B-2"]}Stock levels per SKU.
create-orderan eBay order object (see mock-order)Idempotent in Odoo; honors dry-run.
tracking{"odoo_order_id": 123}odoo_order_id is numeric, not SO….
mock-order{"sku"?, "buyer_index"?, "num_line_items"?}Offline — generates a test order.

Typical test flow (dry run): generate a mock order, then push it.

python3 scripts/sales.py mock-order < /dev/null \
  | python3 scripts/sales.py create-order

create-order returns {odoo_order_id, odoo_order_name, already_existed, confirmed, confirm_error, ...}. already_existed: true means Odoo already had this eBay order — an idempotent skip, not an error.

Accounts Payable — scripts/ap.py

ActionInput (stdin JSON)
search-pos{"search"?, "vendor"?, "state"?, "limit"?}
get-po{"po_id": 123}
update-po-lines{"po_id": 123, "lines": [{"line_id", "price_unit"}], "freight_cost"?, "fees_cost"?}
create-bill{"po_id": 123, "vendor_bill_number"?, "invoice_date"?, "line_ids"?, "reviewer_user_id"?, "review_note"?, "expected_total"?, "tolerance"?}
get-bill{"bill_id": 456}
search-vendors{"search"?, "limit"?}

The AP flow is: find the PO (search-posget-po), correct line prices / freight / fees if needed (update-po-lines), then create-bill. The bill is created in draft; Odoo's create() override auto-adds fee/freight/misc lines, and the reviewer receives an Odoo activity to verify and post it. Pass expected_total + tolerance (default 0.05) to have the server flag mismatches.

Production scheduling (MRP) — scripts/production.py

ActionInput (stdin JSON)
overview{"batch_detail"?, "batch_limit"?, "unscheduled_only"?}
list-batches{"unscheduled_only"?, "limit"?, "offset"?}
get-batch{"batch_id": 142}
schedule{"batch_id", "primary_workcenter_id"?, "production_center_id"?, "date_planned_start"?, "date_planned_finished"?, "activity_message"?}
plan{"batch_id": 142}
bulk-schedule{"atomic"?, "updates": [{"batch_id", ...fields}]}
list-workcenters{"active_only"?}
get-workcenter{"workcenter_id": 3}
production-centers(none)
decoration-methods(none)

Start a planning pass with overview (one round-trip: open batches + workcenters with their current load + reference data). Pull get-batch for the batches you intend to place (it returns eligible_workcenters, eligible_production_centers, decoration readiness, and per-MO durations), then write decisions with schedule (single) or bulk-schedule (many).

The four writable scheduling fields are primary_workcenter_id, production_center_id, date_planned_start, date_planned_finished. Partial updates are fine. The server applies them in safe order and auto-derives production_center_id from the workcenter and date_planned_finished from the start unless you set them explicitly. plan runs Odoo's native slot allocator and requires a workcenter to already be set.

Example: schedule one batch

echo '{"batch_id": 142, "primary_workcenter_id": 3,
       "date_planned_start": "2026-06-10T14:00:00",
       "activity_message": "Auto-scheduled by agent"}' \
  | python3 scripts/production.py schedule

Errors

Scripts exit non-zero and print {"error": {...}} on failure:

  • config_error (exit 2) — ODOO_URL / ODOO_API_KEY missing or malformed.
  • api_error — Odoo returned a non-2xx (includes status and body). 401 means a bad ODOO_API_KEY; 404 on get-* means the record doesn't exist.
  • connection_error — Odoo unreachable / timed out.
  • validation_error — bad input JSON or missing required field.
  • unknown_action / usage (exit 2) — bad CLI invocation; the message lists the valid actions.

Surface the human-readable message to the user. Do not retry on config_error, validation_error, or a 401 api_error.

Safety

  • Treat ODOO_API_KEY as a secret — the scripts read it from the environment and never echo it.
  • Use ODOO_DRY_RUN=true until you've confirmed the data mapping. Confirm vendor-bill creation and production schedule writes with the user before running them against a live (non-dry-run) Odoo.

References