Skip to main content
Merchant product routes use bearer token authentication:
Two gift-card balance-check routes are public and take no Authorization header: POST /v2/giftcards/customer/balance-check and POST /v2/giftcards/programs/{programId}/balance-check. Everything else in the public schema requires a Bearer secret. Production base URL: https://api.loyalty.dog. Public product routes are under /v2. The machine-readable public schema is openapi.public.json (SWE-1133). /openapi.json is the full app schema (login, MFA, API Keys, signup) and is not the public product.

Two credential kinds

There is no public issuance API. Dashboard create/rotate/revoke are not on the public OpenAPI. Merchants subscribe to API Access from the same API Keys page (Stripe Checkout / Customer Portal). That plan does not change JWT or legacyToken behavior. Freeze and metering apply only to hashed ld_* keys.
Changing a JWT App Key or opaque legacyToken 401/403/429 body is a regression (SWE-1181). Hashed ld_* keys use a separate envelope.

Scopes (ld_* only)

JWT App Keys have implicit merchant access. A hashed key is least-privilege (default: no scopes). Typical public reads need loyalty:read. Gift-card redeem needs giftcards:redeemfullAccess on a public key does not grant it. Missing scope → 403 with code: forbidden naming the missing scope.

Identity ping

GET /v2/token with a valid Bearer returns the caller. Unscoped ld_* keys can ping identity; product routes still need scopes.

Rotating tokens

Treat tokens like passwords.
  1. Create a new API Key in the dashboard.
  2. Deploy the new secret to your services.
  3. Revoke the old key.
Use a secrets manager — AWS Secrets Manager, GCP Secret Manager, HashiCorp Vault, Infisical, or your platform’s equivalent — and never bake tokens into images or commit them.

Common errors

Next steps

Quickstart

Walk through your first authenticated request.

API playground

Try endpoints in Mintlify from the public OpenAPI.