ERP and accounting sync
Sokisoko pushes confirmed orders and issued invoices out to your ERP and takes stock and master data in, over signed, idempotent connections. Connections are set up under Settings → ERP sync by an admin; this page is for the person on the other end.
Providers
| Provider | Direction | Auth | Needs platform credentials |
|---|---|---|---|
Custom webhook (generic_webhook) | Orders and invoices out; inventory in | HMAC-SHA256 with a per-connection secret | No |
| Odoo | Orders out; customers, products, stock and prices in | API key | No |
| SAP S/4HANA (OData) and SAP Business One (Service Layer) | Orders out; products, stock per plant/warehouse, business partners and prices in; live availability and price at checkout | Client credentials / session | No |
| QuickBooks Online, Xero, Dynamics 365 Business Central | Invoices and customers, with app-level inbound webhooks | OAuth 2 consent | Yes — see Configuration |
Any system with an HTTP endpoint can integrate through the custom webhook; the named providers wrap each system's own API.
Outbound: the custom webhook
Once a connection has an endpoint and a secret, the hourly sweep (or Sync now in the console) pushes each confirmed order and issued invoice that has not been delivered yet:
POST <your endpoint> HTTP/1.1
Content-Type: application/json
X-Webhook-Signature: <hex HMAC-SHA256 of the body, keyed with the connection secret>
Idempotency-Key: <stable 32-char key derived from entity + operation>
{ …the order or invoice document… }
- The signature is verified exactly as for webhooks;
X-Sokisoko-Signatureis sent too for older consumers. - The idempotency key is the same every time the same document is pushed, so a retry after a timeout must not create a second record on your side.
- Answer
2xx. If your response body is JSON with anexternal_id, it is stored as the record's external reference and shown in the console's provenance panel. Any other status marks the push failed and it is retried on the next sweep. - Every attempt is logged under Settings → ERP sync → sync log with direction, entity, operation, status and error — that log shows you the exact document body a connection sends.
Inbound: stock from your system
Each connection has an inbound URL the ERP can call:
POST /webhooks/erp/{connectionID} HTTP/1.1
Content-Type: application/json
X-Webhook-Signature: <hex HMAC-SHA256 of the body, keyed with the connection secret>
{ "event_id": "wh-2026-09-05-00042", "entity_type": "inventory", "sku": "M12-HEX-40", "quantity_on_hand": "1450" }
event_idandentity_typeare required. The event is deduplicated onevent_idonce applied successfully, so redelivering is safe; a failed apply is not deduplicated and will be retried when you resend.entity_type: "inventory"sets the product's on-hand quantity by SKU. Other entity types are accepted and logged as skipped.- If the connection has a secret, unsigned or badly signed calls are refused with
401 bad_signature. Set a secret.
The OAuth providers use a single app-level inbound URL instead (/webhooks/erp/provider/{provider}) verified with the provider's own signature scheme; their events are routed to the right connection by the source account in the body.
Master data, authority and backfill
For providers that sync master data (Odoo, SAP), inbound changes carry only an id; the connector fetches the record and upserts it by external reference. Two settings shape this, both in the console:
- Sync policy —
erp_authoritative(default) lets inbound updates overwrite local records;sokisoko_authoritativekeeps local edits and only imports net-new records. A staff member can also claim or release authority per product or customer from the record's provenance panel. - Backfill — pull existing ERP master data into Sokisoko when connecting, through the same path as live events.
- Plant → warehouse map (SAP) — routes polled stock per plant to the matching Sokisoko warehouse.
At checkout, SAP connections can answer live availability and per-customer price; the storefront falls back to the local mirror on timeout.