Documentation

Order aggregation

Pull orders from every channel into a unified list and write fulfillment status back.

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

POST/sales-channel/orders/sync/:channelIdJWT

Trigger 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"}'
FieldTypeDescription
fromDateISO date

Pull orders created on or after this timestamp.

toDateISO date

Upper bound on creation time.

statusstring

Channel-native status filter (open, unshipped, pending).

POST/sales-channel/orders/syncJWT
Pull from every connected channel in parallel.

The 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:

ChannelWebhook path
ShopifyPOST /upstream/webhooks/shopify/orders
WooCommercePOST /upstream/webhooks/woocommerce/orders
Amazon SP-APIPOST /upstream/webhooks/amazon/notifications (via SQS subscription)
eBayPOST /upstream/webhooks/ebay/notifications
TikTok ShopPOST /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

GET/sales-channel/ordersJWT

Unified list across every channel.

Query paramDescription
channelFilter to one channel ID
statuspending / processing / shipped / delivered / cancelled / refunded
fromDate, toDateCreated window
page, pageSizePaging
curl "https://appengine.appmint.io/sales-channel/orders?channel=amazon&status=processing" \
  -H "Authorization: Bearer $JWT" -H "orgid: $ORG"

GET/sales-channel/orders/:orderIdJWT
One order with full normalized payload.

The 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

GET/sales-channel/orders/stats/summaryJWT

Counts 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.

PUT/sales-channel/orders/:orderId/statusJWT
curl -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 MFNOrderStatus confirm-shipment with carrier and tracking.
  • Shopify — creates a fulfillment record on the order with the tracking URL.
  • eBay — calls CompleteSale with shipping details.
  • WooCommerce — updates order status to completed and posts an order note with tracking.
  • Walmart — calls shippingUpdates with 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:

  1. Pick & pack happens in Storefront (or your WMS).
  2. The shipping label is created via the Logistics module — which writes a tracking_number and transitions the local order to shipped.
  3. An automation triggers on data_updated for the local order and calls PUT /sales-channel/orders/:orderId/status to 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.