# Order history window

An Admin token without the read_all_orders grant sees only orders from the last 60 days of the simulator's clock, as in Shopify; bind grants to a token to widen it.

The order history window is Shopify's rule that an Admin app holding `read_orders` but not `read_all_orders` reads only orders created or processed in the last 60 days. The simulator applies it on its own clock, so you can test an app that loses sight of old orders. The window holds for `orders`, `order(id:)` and `ordersCount` alike. Load the fulfillment desk scenario, age its orders out of the window and read them with and without the grant:

```bash
ADMIN="$RYSTIC_URL/admin/api/2026-10/graphql.json"
curl -s -X POST "$RYSTIC_URL/_rystic/scenario" -d '{"name":"shopify_fulfillment_desk"}'
curl -s "$ADMIN" -H "X-Shopify-Access-Token: shpat_placeholder" -H "Content-Type: application/json" -d '{"query": "{ ordersCount { count } }"}' | jq -c '.data.ordersCount'
# -> {"count":5}
curl -s -X POST "$RYSTIC_URL/_rystic/clock" -d '{"advance_seconds": 7776000}'
curl -s "$ADMIN" -H "X-Shopify-Access-Token: shpat_placeholder" -H "Content-Type: application/json" -d '{"query": "{ ordersCount { count } }"}' | jq -c '.data.ordersCount'
# -> {"count":0}
curl -s -X POST "$RYSTIC_URL/_rystic/credentials" -d '{"bindings": {"shpat_history": {"actor": "member", "grants": ["read_orders", "read_all_orders"]}}}'
curl -s "$ADMIN" -H "X-Shopify-Access-Token: shpat_history" -H "Content-Type: application/json" -d '{"query": "{ ordersCount { count } }"}' | jq -c '.data.ordersCount'
# -> {"count":5}
```

### Which orders the window hides

An order is outside the window when its `createdAt` and its `processedAt` are both more than 60 days before the simulator's clock. A hidden order is absent from `orders` and `ordersCount`, and `order(id:)` returns `null` for it, as for an id that does not exist. The window moves with the clock: `POST /_rystic/clock` and a scenario's own clock change which orders a token sees. The orders the scenarios seed are dated within 60 days of their clock, so each token sees all of them at boot.

### Grants

A grant is one of the Admin access scopes the simulator knows:

- `read_orders` and `write_orders`
- `read_all_orders`
- `read_assigned_fulfillment_orders` and `write_assigned_fulfillment_orders`
- `read_merchant_managed_fulfillment_orders` and `write_merchant_managed_fulfillment_orders`
- `read_third_party_fulfillment_orders` and `write_third_party_fulfillment_orders`

Only `read_all_orders` changes a response: the window is the one rule that reads a grant.

`POST /_rystic/credentials` binds tokens to an actor and its grants as `{"bindings": {"<token>": {"actor": "member", "grants": [...]}}}`, and returns 204 with no body. Each call replaces every earlier binding, and loading a scenario clears them, so bind after the scenario loads. A token with no binding, or bound with a bare label such as `"member"`, holds no grant and sees the window. An empty `grants` list holds none either. A grant the simulator does not know is refused with 400, and the error lists the ones it does.

A boot file binds the same tokens under a `credentials` key beside `seed`, without the `bindings` wrapper: `{"seed": {...}, "credentials": {"shpat_history": {"actor": "member", "grants": ["read_all_orders"]}}}`. A `POST /_rystic/seed` document of that shape binds them too, and replaces earlier bindings as `POST /_rystic/credentials` does.

---

Source: https://www.rystic.ai/docs/simulators/shopify/features/order-window · Markdown: https://www.rystic.ai/docs/simulators/shopify/features/order-window.md
