ml-connector
OdooStedi

Odoo and Stedi integration

Odoo runs your purchasing and general ledger. Stedi translates your purchase orders into the EDI format your trading partners require and parses their invoices and shipments back into a format Odoo understands. Connecting them eliminates the manual translation step and keeps your procurement and accounts payable in sync. Purchase orders you create in Odoo reach your suppliers as EDI 850s within minutes, and the invoices and advance shipment notices your suppliers send are automatically posted into Odoo without re-keying.

How Odoo works

Odoo exposes purchase orders, suppliers, invoices, GL accounts, and analytic cost centers through its XML-RPC and JSON-2 APIs, authenticated with an API key paired with a username. Polling with a high-water-mark timestamp on the write_date field is recommended for production use. Odoo's custom pricing plan is required for external API access, and the integration user's Odoo access rights and record rules are enforced on every call. XML-RPC is scheduled for removal in Odoo 22 in 2028, so newer implementations should target JSON-2.

How Stedi works

Stedi exposes EDI transactions and file execution through a REST API authenticated with an API key in the Authorization header. Inbound EDI is received from trading partners via SFTP, FTPS, or AS2 and parsed into JSON, then pushed to a registered webhook endpoint as transaction.processed events. Outbound writes require an Idempotency-Key header for deduplication within a 24-hour window. Webhook endpoints must respond within 5 seconds and use publicly trusted certificates, and Stedi retries failed webhooks up to 4 times over 90-second intervals.

What moves between them

Purchase orders and suppliers flow from Odoo to Stedi. Odoo purchase orders are polled on a schedule, translated to X12 850 format, and sent to Stedi for routing to the trading partner via SFTP or AS2. Advance shipment notices and invoices flow inbound from trading partners through Stedi's EDI parsing to a JSON webhook, where ml-connector receives them and posts them into Odoo as purchase receipts and invoices, mapped to the originating purchase order and the supplier in Odoo's master file. GL accounts and cost allocations are mapped at configuration time so each posted invoice is allocated to the correct expense account and cost center.

How ml-connector handles it

ml-connector polls Odoo on a configurable schedule, reads purchase orders with a high-water-mark on write_date, and hands them to Stedi's API with the Idempotency-Key header for deduplication. On the Stedi side, ml-connector registers a webhook endpoint that receives parsed EDI as JSON from inbound 856 advance shipment notices and 810 invoices. When a webhook arrives, ml-connector matches the transaction to the originating purchase order in Odoo using the reference number, maps the supplier to the existing res.partner record, and creates the corresponding account.move and account.move.line records in Odoo's GL with the amounts allocated to the analytic cost center specified on the purchase order. Both API keys are stored encrypted. Stedi webhooks require a response within 5 seconds, so ml-connector enqueues heavy GL operations asynchronously and returns 202 Accepted immediately. Every purchase order and invoice carries an audit trail and can be replayed if a downstream call fails.

A real-world example

A mid-sized distributor imports components from three major suppliers via EDI and manufactures finished goods for retail customers. Before the integration, the procurement team exported purchase orders from Odoo every morning, manually translated them to X12, and sent them to suppliers via SFTP. When suppliers sent back invoices and shipment notices, the team re-entered the quantities and amounts into Odoo by hand. With Odoo and Stedi connected, each purchase order created in Odoo automatically translates and routes within minutes, and inbound shipment notices update the purchase receipt immediately while invoices post to the GL in their final form. The month-end close now starts with accounts payable fully reconciled, and the data-entry backlog is eliminated.

What you can do

  • Poll Odoo purchase orders and suppliers on a schedule, translate them to X12 850 format, and send them to Stedi for routing to trading partners via SFTP or AS2.
  • Receive parsed EDI 856 and 810 transactions from Stedi as JSON webhooks and post them into Odoo as purchase receipts and invoices mapped to the originating purchase order.
  • Map suppliers, GL accounts, and analytic cost centers between Odoo and Stedi so every line item lands on a valid account and cost allocation.
  • Store both API keys encrypted, handle Odoo API key authentication and Stedi Idempotency-Key deduplication, and retry with backoff if a call fails.
  • Maintain a full audit trail on every purchase order and invoice, with the ability to replay a transaction if a downstream operation fails.

Questions

Which direction do purchase orders and invoices move between Odoo and Stedi?
Purchase orders and suppliers move from Odoo to Stedi for translation and routing to trading partners. Advance shipment notices and invoices move inbound from trading partners through Stedi to Odoo as JSON webhooks, where they are posted as purchase receipts and GL transactions. GL accounts and cost centers are mapped at configuration time so the correct allocations are applied.
Does Stedi require any special request headers for the integration to work?
Yes. Stedi's outbound API calls require an Idempotency-Key header for deduplication within a 24-hour window to prevent duplicate invoices if a webhook is retried. ml-connector automatically includes this header on every write. Stedi webhook responses must arrive within 5 seconds, so ml-connector enqueues long-running GL operations and responds immediately with a 202 Accepted.
How does the integration handle Odoo's high-water-mark polling and Stedi's webhook retries?
ml-connector polls Odoo on a schedule you control, using a high-water-mark timestamp on the write_date field to fetch only new and changed purchase orders since the last poll. For inbound Stedi webhooks, ml-connector tracks the eventId to deduplicate if Stedi retries, ensuring a single supplier invoice is not posted to Odoo twice even if the webhook is delivered multiple times.

Related integrations

Connect Odoo and Stedi

Free to use. Add your credentials, ping your real systems, and see if we fit.

Get started