List Orders
GET /cdp/commerce/orders — list your brand’s orders, scoped to your shop. Orders
are served from the CDP’s local synced store (no live Shopify call) and returned in
a normalized, backend-agnostic shape — the raw Shopify payload is never exposed.
Requires the beta:cdp-commerce permission on your brand.
Request
Section titled “Request”GET /cdp/commerce/ordersAuthorization: Bearer vyg_…Query parameters
Section titled “Query parameters”| Param | Type | Default | Description |
|---|---|---|---|
limit | integer | 25 | Page size, clamped to a maximum of 100. |
offset | integer | 0 | Offset; offset + limit must stay within the 10,000-row window or the request is rejected 400. |
created_at_gte | string | — | Inclusive lower bound on the order’s created_at (ISO 8601). |
created_at_lte | string | — | Inclusive upper bound on the order’s created_at (ISO 8601). |
state | string | — | Filter by order state: pending, draft, complete, delivered, cancelled. |
billing_status | string | — | Filter by billing status: billable, processing, complete, on_hold. |
customer_email | string | — | Only orders whose contact matches this normalized email. |
customer_phone | string | — | Only orders whose contact matches this phone (normalized to E.164). |
customer_id | string | — | Only orders whose contact matches this Shopify customer id. |
When more than one customer_* filter is supplied, they resolve to a single
customer by precedence (email › Shopify customer id › phone). An identifier that
matches no customer in your brand returns an empty page — never another brand’s
orders.
Response 200
Section titled “Response 200”{ "list": [ { "id": "b2c1…", "external_id": "4501234567890", "number": "1001", "state": "complete", "billing_status": "complete", "total": "120.00", "currency_code": "USD", "customer": { "contact_id": "c9f0…" }, "created_at": "2026-03-02T14:21:00.000Z", "recovered_at": null } ], "totalSize": 1, "offset": 0, "pageSize": 25, "scope": "your-shop.myshopify.com", "nextCursor": null}| Field | Type | Description |
|---|---|---|
list | array | The page of normalized orders (summary shape — see Get Order for line items). |
totalSize | integer | Total orders matching the filters. |
offset | integer | Offset this page started at. |
pageSize | integer | Effective page size. |
scope | string | Your brand’s connected shop domain. |
nextCursor | string | null | Always null for orders — page with offset. |
Each order’s customer.contact_id is the local contacts.id — pass it straight to
Get Customer (GET /cdp/customers/{contact_id}) or
Customer Orders to pull that customer’s full record
or history. It resolves with matched_by: "contact_id".
Example
Section titled “Example”curl -s "https://cdp.vyg.app/cdp/commerce/orders?created_at_gte=2026-01-01&state=complete&limit=25" \ -H "Authorization: Bearer vyg_your_key_here"Errors
Section titled “Errors”| Status | When |
|---|---|
400 | A deep offset past the result window, or an invalid date / state / billing_status value. |
401 | Missing or invalid credential. |
403 | Brand not enrolled in the commerce beta (beta_not_enabled), or no connected Shopify integration (integration_not_connected). |
405 | Non-GET method. |
See Errors for the full envelope and Tenant Isolation & Scope for why cross-brand data is never returned.