Data synchronization
Standard for ERP, PIM, WMS, and marketplace connectors.
Modes
1. Full sync (bootstrap)
Use once per connection or after disaster recovery.
cursor = null
loop:
page = GET /v1/products?limit=250&cursor=cursor
upsert_local(page.data)
cursor = page.pagination.next_cursor
break if not page.pagination.has_more
store sync_checkpoint = now()
Run off-peak; respect rate limits; resume from last cursor on failure.
2. Incremental sync
Pull
GET /v1/products?updated_since=2026-08-01T10:00:00Z&limit=250&cursor=...
Push (preferred)
Subscribe to webhooks (product.updated, inventory.changed, …) and apply locally. Keep a reconcile pull (e.g. every 6–24 h) for missed deliveries.
3. Event cursor
For enterprise event streams (when contracted):
GET /v1/events?after_event_id=evt_01J...&limit=100
Monotonic event_id — safer than wall-clock alone under clock skew.
Conflict resolution
Declare a system of record per field group in your integration design.
| Domain | Typical SoR | On conflict |
|---|---|---|
| Product title / description | PIM or IoneShop | Last-write-wins with updated_at; or PIM wins on scheduled push |
| Price | ERP / pricing engine | ERP overwrites store on schedule; flash sales may reverse SoR temporarily (document!) |
| Inventory | WMS | WMS absolute set; never “add delta” from two writers |
| Orders | IoneShop | External systems consume; fulfillments may write tracking back |
| Customer profile | CRM or IoneShop | Merge rules; never duplicate identities blindly |
Inventory rules (critical)
- Prefer absolute quantity updates with
location_id+sku - Include
updated_at/versionfrom source - Reject stale writes when
If-Match/ version mismatches (409 CONFLICT) - Single writer per location when possible
Orders
- Create orders from external channels via documented import APIs (Enterprise) or checkout — do not invent parallel order stores as SoR
- Status transitions must follow allowed state machine; invalid jumps →
409 INVALID_STATE_TRANSITION
Checkpoint storage
Persist:
{
"resource": "products",
"mode": "incremental",
"updated_since": "2026-08-01T12:00:00Z",
"cursor": null,
"last_event_id": "evt_01J...",
"last_success_at": "2026-08-01T12:05:00Z"
}
After crash, resume from checkpoint with a small overlap window (e.g. updated_since - 5m) and upsert idempotently.