Built to be inspected.
If you're evaluating build-vs-buy, this is the part that usually decides it. Here is exactly how the API, the two-way Shopify sync and the webhook layer actually work — not a pitch deck.
A JSON REST API on api.retailcommerceos.com (Hono on the Bun runtime) plus a WebSocket channel for live order, inventory and sync events. No GraphQL gymnastics — predictable resource URLs.
Browser sessions use HttpOnly cookies (Better Auth). Server-to-server integrations use scoped API keys passed as a Bearer token — issued per workspace, revocable, and never logged.
Customers, orders, inventory and products are one normalized Postgres schema shared by every module — not eleven apps with eleven copies. Read it once, trust it everywhere.
Every request is scoped to the calling workspace at the query layer. An API key can never read or write another tenant's data, even with a guessed ID.
Scoped keys, revocable any time
Issue a per-workspace API key from settings, pass it as a Bearer token, revoke it the moment a contractor leaves. Keys are stored hashed; the raw value is shown once at creation and never appears in logs.
# Server-to-server requests use a scoped workspace API key.
curl https://api.retailcommerceos.com/api/orders?limit=50 \
-H "Authorization: Bearer wsk_live_••••••••••••••••" \
-H "Accept: application/json"
# 200 OK — resumable cursor for the next page
{
"data": [ { "id": "ord_8fk3...", "code": "#1042", "total": 4990, ... } ],
"nextCursor": "eyJpZCI6Im9yZF84Zmsz..."
}The hard parts, documented
Every vendor says 'two-way sync.' The edge cases live in conflict resolution, idempotency and retries — so here is how each one is handled.
When Shopify and Retailos both write the same record, resolution is field-level and last-writer-wins by source timestamp, with inventory treated as authoritative on the Retailos side. No silent clobbering — the losing value is recorded in the sync audit log so you can see exactly what changed and revert it.
Every inbound webhook and push carries an idempotency key. Replays (Shopify retries aggressively during flash sales) are de-duplicated, so a doubled webhook never doubles an order or an inventory adjustment.
Outbound pushes that fail are retried with exponential backoff via BullMQ. After max attempts they land in a dead-letter queue surfaced in the in-app Sync Health panel — failures are visible and replayable, not lost.
A scheduled job diffs Retailos against Shopify every day and reconciles divergence (deletes, manual Shopify edits, missed webhooks). GID-matched so renamed or re-handled products still line up.
// Every webhook we send is HMAC-signed and carries an idempotency key.
// Verify the signature, then de-dupe on the key before you act.
POST https://your-app.example.com/retailos-hook
X-Retailos-Signature: sha256=4a7d... // HMAC-SHA256 of the raw body
X-Retailos-Idempotency-Key: evt_3c9a1f... // stable across retries
X-Retailos-Topic: inventory.level.updated
{
"topic": "inventory.level.updated",
"workspaceId": "ws_2b81...",
"occurredAt": "2026-06-15T11:28:56.439Z",
"data": { "sku": "RING-22K-007", "locationId": "loc_surat_01", "available": 3 }
}Reliable when it matters most
Webhooks are HMAC-signed and idempotency-keyed. We retry with exponential backoff and dead-letter what we can't deliver — so a peak-sale traffic spike degrades gracefully instead of dropping events on the floor.
A representative slice of the API
REST resources are predictable and workspace-scoped. The full reference (with request/response schemas and an OpenAPI spec) is shared with technical evaluators on request.
| Method | Endpoint | What it does |
|---|---|---|
| GET | /api/products | List & filter products with variants and live stock. |
| GET | /api/orders | Resumable cursor pagination across POS, online & B2B. |
| POST | /api/orders | Create an order; inventory decrements atomically. |
| GET | /api/customers | Unified customer profiles with order history & LTV. |
| GET | /api/inventory/levels | Per-location stock; the single source of truth. |
| POST | /api/shopify/sync | Trigger a two-way reconciliation run on demand. |
| GET | /api/sync/health | Webhook health, DLQ depth & last reconciliation. |
| POST | /api/webhooks/subscribe | Register your endpoint for order/inventory events. |
Per-IP and per-workspace limits protect every endpoint. Limits are returned in X-RateLimit-* headers so you can back off cleanly. Higher quotas on Pro & Enterprise.
Spin up a free trial workspace, connect a Shopify dev store, and run a synthetic load test against real sync behaviour before you commit a single engineering hour. See migration.
Full export of products, orders, customers and inventory as JSON/CSV at any time — no lock-in. If you ever leave, you take a complete copy with you.
Want the full reference and an API key?
We'll share the complete endpoint reference, the OpenAPI spec, sync-latency benchmarks and a sandbox so your team can validate it firsthand — before you remove anything you've already built.
Inspect it before you trust it.
That's the point. Connect a dev store and put the sync under load — no card required.