A Token-tier agent credential identifies your app. A buyer-linked token also carries the signed-in Shop customer. That is the difference between “an agent is shopping” and “this buyer is shopping through an agent.”
As of Sep 2026, Shopify documents a UCP delegated identity provider flow: authorize with Shop (accounts.shop.app), exchange the Shop access token for a short-lived JWT grant, redeem that grant at Shopify for a buyer-linked JWT. The resulting token lasts about 60 minutes and does not refresh. When it expires, remint from the Shop session.
Official reference: Create a buyer-linked token. Pair with UCP agent profiles, auth and rate limiting, and secure agentic commerce.
Why buyer linkage matters
With a buyer-linked token you can:
- Return personalized Global Catalog search results
- Sign the buyer into a merchant store checkout path
- Apply automatic discounts that depend on the signed-in customer
- Operate at Token-tier limits with purchase scopes when granted (for example
dev.ucp.shopping.checkout:manage)
Without it, you may still build carts anonymously or with an app-only token, but you miss buyer-aware behavior and you still need the right permission story for complete_checkout.
Think of it as identity linking for agentic checkout, not as a forever API key.
The three-step chain (server-side)

Confidential client secret stays on a server you control. Public clients cannot complete this flow safely. Do not ship the secret in browser or mobile binaries.
Discover endpoints at runtime (do not hard-code forever):
- Resource server
/.well-known/oauth-protected-resource→ Shopify authorization server - Shopify UCP business profile →
dev.ucp.common.identity_linking→ Shop as delegated IdP - Shop
/.well-known/oauth-authorization-server→ authorize + token endpoints
Then:
1. Authorize the customer with Shop
Standard OAuth authorization code against Shop. Reuse Dev Dashboard client id/secret and redirect URI. Request every scope you plan to redeem later (include checkout manage if you will call checkout tools).
You receive a Shop access_token (example responses show expires_in: 3600).
2. Exchange at Shop for a JWT grant
Token exchange (RFC 8693) at Shop’s token endpoint:
grant_type=urn:ietf:params:oauth:grant-type:token-exchangesubject_token= Shop access tokenrequested_token_type= JWTaudience=api.shopify.com(Global Catalog) or the merchant store domain for store checkout
The returned access_token is a JWT authorization grant: signed, single-use, about 60 seconds to live. It is not your API bearer yet.
3. Redeem at Shopify for the buyer-linked token
JWT bearer assertion (RFC 7523) at Shopify’s (or the store’s) token endpoint with the scopes you need. Shopify verifies the grant against Shop’s keys, resolves the customer, and issues the buyer-linked JWT.
For merchant checkout, discovery points at the store’s authorization server; set audience to the store domain and request scopes such as openid and dev.ucp.shopping.checkout:manage as documented for signed-in checkout tools.
TTL reality: 60s grant, ~60 min token, no refresh

Two clocks, often confused:
| Artifact | Lifetime (documented) | Refresh? |
|---|---|---|
| JWT authorization grant from Shop | ~60 seconds, single-use | No; re-exchange if needed |
| Buyer-linked token from Shopify | ~60 minutes | No refresh token; remint via the chain |
Build session handling around reminting, not around refresh_token muscle memory from classic OAuth apps. Cache the buyer-linked JWT only within its lifetime, keyed to the buyer and resource server, on the server.
If complete_checkout still fails with a Token-tier client, check purchase permission and merchant/agent eligibility separately. Community threads show scope alone is not always sufficient; treat platform policy as part of the design.
Implementation checklist
- Keep client secret server-side only.
- Discover auth URLs from well-known metadata; honor cache headers.
- OAuth the buyer to Shop with the scopes you will redeem.
- Exchange with the correct
audience(global vs store). - Redeem promptly before the 60s grant expires.
- Send the buyer-linked JWT as Bearer on MCP calls that need buyer context.
- Remint near expiry; do not expect a refresh token.
- Pair with a real agent profile and the right trust tier expectations.
- Prefer Cart MCP for browsing; Checkout MCP when committing (cart migration notes).
Failure modes to expect
- Grant expired or reused: exchange again; grants are single-use and short.
- Wrong audience: catalog grant redeemed at a store (or the reverse).
- Browser exchange: secret leakage; move the flow to your backend.
- Missing checkout scope: token works for search but not manage checkout.
- Assuming refresh: sessions die at ~60 minutes unless you remint.
Log correlation ids and HTTP status from each hop. Do not ask the model to “retry checkout” when the token is simply dead.
Takeaways
- Buyer-linked tokens bind a Shop customer to your agent credential for personalized and signed-in commerce.
- Flow: Shop OAuth → token exchange (JWT grant) → Shopify JWT bearer redeem.
- Run exchange and redeem only on a confidential server.
- Grant ~60s single-use; buyer-linked token ~60 minutes with no refresh.
- Discover endpoints; set audience to global catalog or merchant store deliberately.
- Remint from the Shop session; design UX for re-link, not silent forever tokens.
When your agent’s checkout fails at minute 61, is the model confused about tools, or did you forget that buyer-linked JWTs die without a refresh token?