Shopify Sync
When Sync to Shopify is enabled on a transfer order, Synplex pushes transfer data to Shopify's native Inventory Transfer API. This keeps Shopify's inventory records in sync with transfers managed in Synplex.
Sync Toggle
Each transfer has a syncTransferOrderToShopify boolean field.
- Shop-level default: set in Settings → Sync transfer orders to Shopify by default. When a new transfer is created without this field explicitly set, the backend reads and applies the shop's default automatically.
- Per-transfer: can be set individually at creation time.
- Sync can only be meaningfully changed before confirmation — once a
transfer is confirmed and synced, the
shopifyIdis set and subsequent mutations depend on it.
What Gets Synced and When
| Event | Mutation type | Condition |
|---|---|---|
| Transfer confirmed | TRANSFER_CREATE | Sync enabled, both locations set, at least one active line item |
| Transfer reference or notes updated | TRANSFER_EDIT | Transfer has shopifyId, sync enabled |
| Transfer cancelled | TRANSFER_CANCEL | Transfer has shopifyId, sync enabled |
| Shipment created | SHIPMENT_CREATE | Transfer has shopifyId, sync enabled, estimatedDeliveryDate set (required — throws if missing) |
Shipment estimatedDeliveryDate updated | SHIPMENT_SET_TRACKING | Shipment has shopifyId, sync enabled, parent transfer status = confirmed |
Shipment item quantityAnnounced changed | SHIPMENT_UPDATE_QTY or SHIPMENT_REMOVE_ITEMS | Shipment item has shopifyId, sync enabled, parent transfer confirmed or in_transit |
Shipment item quantityAccepted or quantityDefect changed | SHIPMENT_RECEIVE | Same guards as above |
SHIPMENT_UPDATE_QTYfires when the new announced quantity is > 0.SHIPMENT_REMOVE_ITEMSfires when the new announced quantity is set to exactly 0.
Two Distinct Sync Phases for Shipment Items
Synplex treats quantity announced changes and receipt changes as two mutually exclusive phases that never fire in the same update:
Phase D1 — Announced quantity changed
Fires when quantityAnnounced changes. Enqueues a single
SHIPMENT_UPDATE_QTY or SHIPMENT_REMOVE_ITEMS mutation. Exits
immediately after — D2 does not run in the same update.
Phase D2 — Receipt quantities changed
Fires when quantityAccepted and/or quantityDefect change (but
quantityAnnounced did not change in the same update). Computes deltas
against previous values and enqueues SHIPMENT_RECEIVE mutations for
accepted and defect changes in parallel.
Sync Guards
Before any sync mutation is enqueued, Synplex checks:
- The transfer or shipment must have a
shopifyId(set after a successfulTRANSFER_CREATE) syncTransferOrderToShopifymust be true on the parent transfer- For
TRANSFER_CREATE: both source and destination locations must be set — if missing, the error is written to theshopifySyncErrorfield on the transfer record and an exception is thrown - For
SHIPMENT_CREATE:estimatedDeliveryDatemust be set — throws if missing - For
SHIPMENT_SET_TRACKING: parent transfer status must beconfirmed(notin_transit)
If the sync toggle is false and confirmation is attempted, Synplex logs a SKIPPED entry and the transfer is confirmed in Synplex only — no Shopify record is created.
Queue and Retry Behaviour
All transfer sync mutations run through a background job queue:
| Setting | Value |
|---|---|
| Queue name | shopify-transfer-sync-{shopId} |
| Max concurrency | 2 per shop |
| Retry count | 3 |
| Initial interval | 60 seconds |
| Backoff factor | 2× |
| Max interval | 5 minutes |
| Jitter | Yes |
The transfer sync queue runs at
maxConcurrency: 2, compared to the PO sync queue which runs atmaxConcurrency: 1. This allows two transfer sync jobs to process concurrently per shop.
Sync Log (transferSyncLog)
Every sync attempt — pending, skipped, successful, or failed — is
recorded as a transferSyncLog entry. Log fields include:
| Field | Description |
|---|---|
status | PENDING, SKIPPED, SUCCESS, FAILED |
triggerType | What caused the sync (e.g. TRANSFER_CONFIRMED, SHIPMENT_CREATED) |
mutationType | The Shopify operation attempted (e.g. TRANSFER_CREATE, SHIPMENT_RECEIVE) |
shopifyTransferId | The Shopify GID of the Inventory Transfer, if known |
shopifyShipmentId | The Shopify GID of the Inventory Shipment, if known |
delta | Quantity delta for receipt mutations |
errorMessage | Error detail if the attempt failed |
retryCount | Number of retry attempts made |
shopifySyncError Field
If the TRANSFER_CREATE mutation is blocked by a guard (missing
locations or no active line items), Synplex writes a human-readable
error message to the shopifySyncError field on the transfer record.
This is visible on the transfer detail page and tells you exactly why
the Shopify sync did not fire.
How This Differs from PO Sync
| Transfer Sync | PO Sync | |
|---|---|---|
| Shopify API | Inventory Transfer API | Inventory adjustment mutations |
| Stock buckets | Shopify manages movement | Synplex pushes to incoming / available / damaged |
| Queue concurrency | 2 per shop | 1 per shop |
| Delta baseline tracking | No (uses Shopify's own state) | Yes (syncedQuantityAnnounced etc.) |
| Header field sync | reference and notes on update | Not synced |
| Shipment ETA sync | Yes (SHIPMENT_SET_TRACKING) | No |
| Cancellation sync | Yes (TRANSFER_CANCEL) | No (PO cancel only affects Synplex) |