Skip to main content

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

ProviderDirectionAuthNeeds platform credentials
Custom webhook (generic_webhook)Orders and invoices out; inventory inHMAC-SHA256 with a per-connection secretNo
OdooOrders out; customers, products, stock and prices inAPI keyNo
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 checkoutClient credentials / sessionNo
QuickBooks Online, Xero, Dynamics 365 Business CentralInvoices and customers, with app-level inbound webhooksOAuth 2 consentYes — 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-Signature is 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 an external_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_id and entity_type are required. The event is deduplicated on event_id once 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 policyerp_authoritative (default) lets inbound updates overwrite local records; sokisoko_authoritative keeps 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.