Authentication
Learn how to authenticate requests using JWT tokens, API keys, and webhook HMAC signatures.
The API supports three authentication mechanisms depending on the use case.
JWT Bearer tokens
Most endpoints require a JWT access token passed in the Authorization header:
curl https://api.example.com/v1/reseller_stores
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." Access tokens are obtained via POST /v1/auth/login or POST /v1/auth/register and expire after 15 minutes. Use the refresh endpoint to get a new one.
Token lifecycle
| Token | TTL | Storage |
|---|---|---|
| Access token | 15 minutes | Authorization: Bearer header |
| Refresh token | 7 days | httpOnly cookie (refresh_token) |
The refresh token is automatically rotated on each use — the old token is revoked and a new pair is issued.
JWT payload
The access token contains:
| Claim | Description |
|---|---|
sub | Owner ID (e.g. usr_abc123) |
activeResellerStoreId | Currently active reseller store workspace |
API keys
For server-to-server integrations, use API keys instead of JWT tokens. API keys use the sk_ prefix:
curl https://api.example.com/v1/reseller_stores
-H "Authorization: Bearer sk_live_abc123def456..." The API automatically detects whether the Bearer token is a JWT or an API key by checking for the sk_ prefix.
| Prefix | Environment |
|---|---|
sk_live_ | Production |
sk_test_ | Testing |
API keys are hashed with SHA-256 before storage — the raw key is only shown once at creation time.
Webhook HMAC verification
Shopify webhook endpoints (/v1/orders/webhook and /v1/fulfillments/webhook) are authenticated via HMAC-SHA256 signatures. Shopify signs the raw request body with your store’s webhook secret.
Required headers:
| Header | Description |
|---|---|
X-Shopify-Hmac-SHA256 | Base64-encoded HMAC-SHA256 signature |
X-Shopify-Shop-Domain | Originating Shopify shop domain |
The API looks up the webhook secret by shop domain and verifies the signature using constant-time comparison to prevent timing attacks.
Response
{
"accessToken": "eyJhbGciOiJIUzI1NiIs...",
"expiresAt": 1708700000
}