Orders flow into Sales Channel from two paths: webhook delivery (when the channel pushes) and polling (when it doesn't, or as a backstop). Both paths land orders in a unified aggregated_order collection that normalizes the shape across providers. Status updates flow back outward to keep the channel listing in sync with fulfillment.
Pull orders
/sales-channel/orders/sync/:channelIdJWTTrigger a one-shot pull from a channel. Filter by date range and status:
curl -X POST https://appengine.appmint.io/sales-channel/orders/sync/shopify \
-H "Authorization: Bearer $JWT" -H "orgid: $ORG" \
-d '{"fromDate": "2026-04-20T00:00:00Z", "status": "open"}'
| Field | Type | Description |
|---|---|---|
| fromDate | ISO date | Pull orders created on or after this timestamp. |
| toDate | ISO date | Upper bound on creation time. |
| status | string | Channel-native status filter ( |
/sales-channel/orders/syncJWTThe polling cadence is configurable per channel under the connect config (pollIntervalMinutes). Defaults: marketplaces every 5 minutes, own-store platforms every 15 minutes (own stores typically have webhooks).
Webhooks
Where the channel supports it, configure webhooks during POST /sales-channel/channels/:channelId/enable. Each provider has its own webhook receiver path under Upstream:
| Channel | Webhook path |
|---|---|
| Shopify | POST /upstream/webhooks/shopify/orders |
| WooCommerce | POST /upstream/webhooks/woocommerce/orders |
| Amazon SP-API | POST /upstream/webhooks/amazon/notifications (via SQS subscription) |
| eBay | POST /upstream/webhooks/ebay/notifications |
| TikTok Shop | POST /upstream/webhooks/tiktok/orders |
The receiver normalizes the payload and writes an aggregated_order record. The same flow runs whether the order arrives via webhook or polling.
Read aggregated orders
/sales-channel/ordersJWTUnified list across every channel.
| Query param | Description |
|---|---|
channel | Filter to one channel ID |
status | pending / processing / shipped / delivered / cancelled / refunded |
fromDate, toDate | Created window |
page, pageSize | Paging |
curl "https://appengine.appmint.io/sales-channel/orders?channel=amazon&status=processing" \
-H "Authorization: Bearer $JWT" -H "orgid: $ORG"
/sales-channel/orders/:orderIdJWTThe aggregated order shape:
{
"orderId": "agg_a1b2",
"channel": "amazon",
"channelOrderId": "112-3456789-...",
"status": "processing",
"customer": { "email": "...", "name": "..." },
"shippingAddress": { "country": "US", ... },
"lines": [
{ "sku": "SKU-100", "channelSku": "B0XXXXXX", "quantity": 1, "unitPrice": 19.99 }
],
"totals": { "subtotal": 19.99, "tax": 1.60, "shipping": 4.99, "grandTotal": 26.58 },
"createdAt": "2026-04-25T...",
"channelMetadata": { /* raw channel-specific fields */ }
}
channelMetadata carries fields that don't map cleanly across providers (Amazon IsPrime, Shopify tags, eBay paymentMethods).
Statistics
/sales-channel/orders/stats/summaryJWTCounts and totals by channel and status. Use for dashboards.
Fulfillment writeback
When an order ships, write the status (and tracking number) back to the channel. The channel listing then shows shipped on the customer's side.
/sales-channel/orders/:orderId/statusJWTcurl -X PUT https://appengine.appmint.io/sales-channel/orders/$ORDER_ID/status \
-H "Authorization: Bearer $JWT" -H "orgid: $ORG" \
-d '{"status": "shipped", "trackingNumber": "1Z999AA10..."}'
The provider for the channel translates the status into the channel's own model:
- Amazon — calls
MFNOrderStatusconfirm-shipment with carrier and tracking. - Shopify — creates a fulfillment record on the order with the tracking URL.
- eBay — calls
CompleteSalewith shipping details. - WooCommerce — updates order status to
completedand posts an order note with tracking. - Walmart — calls
shippingUpdateswith carrier and tracking.
Writeback is async. If the channel call fails, the aggregated order keeps the new status locally and the writeback retries with exponential backoff. Failed writebacks surface in GET /sales-channel/sync/history.
Wiring to fulfillment
A typical flow:
- Pick & pack happens in Storefront (or your WMS).
- The shipping label is created via the Logistics module — which writes a
tracking_numberand transitions the local order toshipped. - An automation triggers on
data_updatedfor the local order and callsPUT /sales-channel/orders/:orderId/statusto write back.
Aggregated orders are linked to local Storefront orders by channelOrderId. If you also create a Storefront order for revenue/accounting, store the link in aggregated_order.data.localOrderId.