Authentication
Two-credential token flow — apiKey + secretKey → Bearer access token.
Authentication is a two-credential flow. You exchange your apiKey + secretKey pair for a short-lived Bearer access token, then send that token on every API call. Requiring both halves of the pair means a single leak (e.g. a stray log line, a shared screen) doesn't hand an attacker a working credential.
Your credentials
Each merchant gets two pairs — one for sandbox, one for production:
| Key kind | Prefix | Allowed usage |
|---|---|---|
| Secret · production | sk_live_… | Server-side only. Full access. |
| Secret · sandbox | sk_test_… | Server-side only. Sandbox cascade. |
| Publishable · production | pk_live_… | Browser/native client. Hosted checkout only. |
| Publishable · sandbox | pk_test_… | Browser/native client. Sandbox checkout only. |
secretKey grants full API access. Store it in a secret manager — never commit it or expose it in client-side code. If a key is exposed, rotate the pair from your dashboard.Exchange for a token
Send both keys to POST /v1/auth/token. Both must come from the same environment (test pair or live pair) — pairing them across environments returns 401.
curl -X POST https://sandbox-api.key2pays.com/v1/auth/token \
-H "Content-Type: application/json" \
-d '{
"apiKey": "pk_test_…",
"secretKey": "sk_test_…"
}'{
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6Ikp…",
"tokenType": "Bearer",
"expiresIn": 3600,
"environment": "sandbox",
"merchant": { "id": "MCH-001", "name": "Acme Inc" }
}Use the token
Send the accessToken as a Bearer on every other request:
curl https://sandbox-api.key2pays.com/v1/ping \ -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6Ikp…"
Token lifetime
Tokens are valid for 1 hour. When you receive 401 token_expired, request a fresh token from /auth/token with the same key pair. Most clients cache the token in memory and refresh proactively a minute before expiry.
Legacy raw-key auth
For backward compatibility you can still pass a raw sk_test_… / sk_live_… directly in the Authorization header — the API will accept it as the Bearer. New integrations should prefer the token flow above because it lets you rotate the underlying secret without revoking outstanding sessions.