Atribu
API Reference

Commerce

The merchant's catalogue and the order lookup — the pull half of the commerce sync.

Two reads for a consumer application working on a connected merchant's behalf: the product catalogue, and the "where is my order" lookup. Both require commerce:read.

Products

Endpoint
GET /api/v1/commerce/products

The catalogue with each product's variants nested, keyset-paginated on (updated_at, product_id) ascending.

A webhook is a tickle, not the data

catalog.updated tells you a pull is worth making; it never carries the catalogue. Pass the newest updated_at you have seen as updated_since and walk forward — the ascending order is what keeps a cursor valid no matter how many products change while you page.

Orders

Endpoint
GET /api/v1/commerce/orders

At least one of order_ref, email or phone is required. A call with none answers 400: this is a lookup on a named shopper's behalf, not a dump of the merchant's order history.

No customer identity comes back. You already hold whichever contact you searched with, so echoing it would tell you nothing — and not returning it is what keeps the route from becoming an enumeration tool.

Live store reads

Endpoints
GET /api/v1/commerce/live/products
GET /api/v1/commerce/live/orders

The two reads above serve Atribu's copy of the store. These two read the connected Shopify store live, from Shopify's Admin API, in the request: use them for an initial import and a periodic reconcile, and take deltas from the shopify webhook events. Both require commerce:live, which the commerce connect scope grants together with commerce:read.

  • Products carry every variant, read to the end — variant_id (the id a cart permalink takes), options, price, compare_at_price, inventory_quantity, inventory_policy, tracked — in every status (active, archived, draft).
  • Orders come in every status, with financial_status and fulfillment_status in Shopify's REST spelling (the values the orders/* webhooks carry), attributes (the cart / note attributes, e.g. vitrina_order), and every line with its variant_id and quantity.

Both sort by Shopify's updated_at ascending. Pass updated_since to read a delta and walk pagination.cursor until has_next is false — the cursor carries the filter and the store, so send it alone. meta.connection_id and meta.shop name the store; a profile with several stores needs connection_id. A throttled Shopify response waits for its cost budget and retries rather than failing the page.

Personal data

Every order from GET /api/v1/commerce/live/orders carries the buyer's email and phone. That is why commerce:live is its own scope.

StatusCodeWhen
404not_foundThe profile has no live Shopify connection
400invalid_parameterBad updated_since; several stores and no connection_id
409connection_revokedShopify no longer accepts the store's grant — reconnect it
502provider_errorShopify failed the read (its own message)
503service_unavailableThe token could not be refreshed right now; retry
MethodPathWhat it does
GET/api/v1/commerce/live/ordersRead a connected store's orders live
GET/api/v1/commerce/live/productsRead a connected store's catalogue live
GET/api/v1/commerce/ordersLook an order up
GET/api/v1/commerce/productsList commerce products

Generated from openapi.json. The full request and response schema for every operation is in the OpenAPI document.

Next steps

On this page