Partner credentials (partner id, API key or HMAC secret, webhook secret) are provisioned by our team at onboarding. Request them at pag.finance/businesses.
API key (Bearer) - recommended
Send the key directly in theAuthorization header on every request. No canonical string, no signature, no nonce, no timestamp.
1
Generate a key
Create a key in the dashboard (API and Integrations panel) or via
POST /api/v1/partners/me/api-keys. The full sk_live_... value is shown once only; store it, because it is not recoverable (only the hash is kept).2
Send it on every request
Attach the key exactly as received in the
Authorization header.3
Rotate or revoke
List keys with
GET /api/v1/partners/me/api-keys and revoke one with POST /api/v1/partners/me/api-keys/:keyId/revoke (takes effect immediately). Each partner can hold several keys, for example one per environment or service.HMAC-SHA256 - legacy and advanced
Use HMAC if you already have an HMAC integration or need nonce-based anti-replay. The header carries the partner id, a timestamp, a nonce, and the signature.1
Derive the signing key
signingKey = SHA256(rawSecret + ":" + partnerId). The raw secret never travels and is never stored: only SHA256(secret:partnerId) is kept. The secret is plain text, not base64.2
Hash the body
bodyHash = SHA256_hex( JSON.stringify(JSON.parse(rawBody)) ). The body is normalized before hashing. For a GET or an empty body, hash the normalized empty body.3
Sign the canonical string
signature = HMAC_SHA256_hex(signingKey, canonical) (64 hex chars).4
Build the header
HMAC-SHA256 partnerId=...,timestamp=...,nonce=...,signature=...Timestamp window: 300 seconds (5 minutes); outside it,
401. Anti-replay nonce: deduplicated in Redis for 600 seconds (10 minutes); reuse within that window returns 401. Use a unique nonce per request.End-user JWT
Payment operations (cash-out, cash-in, receipts) run as an end user, not as the partner. Your backend exchanges the user’spubkey or uid for a JWT.
Issue a token
POST /api/v1/auth/token, authenticated by the partner (API key or HMAC).
string
required
Partner credentials:
Bearer sk_live_... or the HMAC header.string
The user’s blockchain address. Provide
pubkey or uid (at least one, minimum 3 characters).string
The user’s internal id, as an alternative to
pubkey.string
default:"config default"
Optional TTL override, for example
1h or 7d. Capped at 30d.string
The signed JWT (HS256). Send it as
Authorization: Bearer <token> on protected routes.string
The effective TTL applied to the token.
string
Always
Bearer.object
{ pubkey, kycStatus, partnerId } for the resolved user.The token carries identity only (
pubkey, uid, partnerId, iss). Issuance refuses a BLOCKED user with 403. The per-operation KYC gate (kycStatus === APPROVED) is enforced on the protected routes, not at issuance. A token minted by another instance is rejected with 401 (the issuer is validated on every call).Token usage
Include the end-user JWT in theAuthorization header of every authenticated user call: