Shopify
What the Shopify connector reads, with which permissions, what it never touches, how it syncs, and the facts it produces.
Last changed Markdown versionllms.txt
Source module: app/connectors/shopify.py. Kind: facts only. Display name: "Shopify".
The order system in the flagship refund story: the agent refunds in Stripe and the order must show as cancelled here. The connector reads orders changed since the watermark through the Admin GraphQL API and turns each into a state fact plus event facts, keyed by the order's numeric id, which is what an agent's tools see.
Auth and scopes
| Item | Value |
|---|---|
| Method | Admin API access token of a custom app, sent as X-Shopify-Access-Token, against https://{shop}/admin/api/{version}/graphql.json (version 2026-07; override with api_version in the credentials) |
| Credentials stored (encrypted) | shop (the *.myshopify.com domain), access_token; optional api_version |
| Least-privilege scopes | read_orders. Add read_customers only if you want customer identities hashed for cross-system linking; without it Shopify refuses the customer field with ACCESS_DENIED, the connector sends the orders query again without it, customer_hid is null, and the connection's health says so. Nothing else. |
| Connection test | { shop { name myshopifyDomain } } |
| How to get the token | Settings → Apps and sales channels → Develop apps → Create an app → Configure Admin API scopes (read_orders) → Install app → Reveal the Admin API access token once |
Fields pulled and why
One query, orders(first: 100, after, query: "updated_at:>='<watermark>'", sortKey: UPDATED_AT), paged by cursor:
| Field | Used for |
|---|---|
legacyResourceId, id, name |
Subject id (numeric order id), order_name attribute |
createdAt, updatedAt |
State fact timestamp, watermark |
cancelledAt, cancelReason |
order_cancelled fact |
displayFinancialStatus, displayFulfillmentStatus |
State attributes and the derived status |
customer.email |
HMAC-hashed into customer_hid; the email is discarded |
refunds { id createdAt totalRefundedSet { shopMoney { amount currencyCode } } } |
refund_created facts |
fulfillments { id createdAt status } |
fulfillment_created facts |
Line items, addresses, names, phone numbers, notes, payment details and metafields are never requested.
Fact types produced
Subject id is the numeric order id (10231), subject kind order.
fact_type |
When | Attributes | raw_ref |
|---|---|---|---|
order_status |
Every order returned (one per updatedAt) |
status (open, cancelled, refunded, partially_refunded), financial_status, fulfillment_status, order_name, customer_hid |
shopify:order:{id}:status:{updatedAt} |
order_cancelled |
cancelledAt set |
reason, customer_hid |
shopify:order:{id}:cancelled |
refund_created |
Each refund on the order | amount (major units), currency, customer_hid |
shopify:refund:{refund_id} |
fulfillment_created |
Each fulfilment | status |
shopify:fulfillment:{fulfillment_id} |
status is derived from fields Shopify reports and nothing else: cancelled when cancelledAt is set, else the
refund state from the financial status, else open. The library refund_workflow template's precondition
state_before_action: {source: shopify, type: order_status, where: {status: eligible}} is a placeholder for your
own policy: with this connector write it against the real fields, for example
where: {financial_status: paid} or where: {status: open}.
Incremental sync, watermark, throttling
- First sync reads every order; later syncs add
updated_at:>='<watermark>'. The watermark is the newestupdatedAtseen, then advanced to the sync time less the safety margin like every connector. - Shopify throttles GraphQL by query cost with HTTP 200 and a
THROTTLEDerror; the connector backs off and retries up to six times. HTTP 401/403 marks the connection for re-authentication. - Upserts are idempotent on
raw_ref; a re-sync changes nothing that did not change.
Claims produced
None.
Limitations
- Orders only. Draft orders, returns (as distinct from refunds), inventory and customer records are not read.
refund_createdcarries the refund's total; per-line refund detail is not read.- Orders archived or deleted in Shopify stop appearing in
updated_atqueries; facts already written remain.