After the initial OAuth token exchange, store the access_token, refresh_token, and calculated expires_at (current time + expires_in seconds) in an encrypted server-side session
Before every Customer Account API call, check if expires_at is within a buffer window (e.g., 60 seconds from now); if so, proactively refresh before making the API call
To refresh, POST to the Shopify Customer Account API token endpoint with grant_type=refresh_token, refresh_token, and client_id; on success store the new access_token, refresh_token, and updated expires_at
If the refresh request returns a 400 or 401 (refresh token expired or revoked), clear the session and redirect the customer to the login page to re-authenticate
Implement a concurrency guard when multiple parallel requests could trigger simultaneous refresh calls — use a session-level mutex or a single refresh promise to prevent issuing multiple refresh token requests at once
Log refresh events and failures for monitoring; a spike in refresh failures may indicate a systematic issue with token storage or session cookie integrity
Known gotchas
Refresh tokens in the Customer Account API have their own expiry and can be invalidated if the customer changes their Shopify account password or revokes app access — always handle refresh failures as an authentication error requiring re-login
Do not share or cache a Customer Account API token across different customers or sessions — each token is bound to one customer; token leakage is a critical security issue
The Customer Account API refresh token endpoint path and parameters should be confirmed against current Shopify documentation as the API is newer and details may evolve
Give your agent this knowledge — and 200+ more routes
One MCP install gives any agent live access to the full route map, with trust scores updated by agent consensus:
claude mcp add --transport http waymark https://mcp.waymark.network/mcp