PayZuDocs

Exchange the credential for a token, send it on each call and know what to do when access is refused.

The credential is a client_id and client_secret pair, created by the account holder in the dashboard with the operation PIN. It operates a single account and only the routes of the scopes it was given, and it can have a list of allowed IPs.

Get the token

Send the credential in Authorization: Basic to POST /oauth/token:

POST /api/v1/oauth/token
Authorization: Basic base64(client_id:client_secret)
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials
{
  "access_token": "eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIn0..mQ3Zy1hbVhpbXBsZQ.ZXhlbXBsbw.c2lnbmF0dXJl",
  "token_type": "Bearer",
  "expires_in": 900,
  "scope": "PAYMENT_WRITE PAYMENT_READ STATEMENT_READ"
}
  • The token is valid for 15 minutes (expires_in: 900). Once it expires, the API responds 401 with TOKEN_INVALID: request another one from the same route.
  • scope lists the credential's scopes, separated by spaces.
  • client_id and client_secret can also go in the body, as application/x-www-form-urlencoded or JSON.
  • The route limits exchanges per client_id and IP. Above the limit, it responds 429 with Retry-After.

Examples in curl and Node.js are in Getting started.

Other ways to authenticate

The API also accepts the credential directly on each call. The three ways give access to the same account, with the same scopes.

WayHeaderThe secret travels
Access tokenAuthorization: Bearer <access_token>Only in the exchange for the token.
Credential in BasicAuthorization: Basic base64(client_id:client_secret)On every call.
Credential tokenAuthorization: Bearer pzu_<prefix>_<secret>On every call. The dashboard shows this token when the credential is created.

The dashboard login does not work on the API routes, and the credential does not work on the dashboard.

Scopes

Each route requires a scope, and no scope includes another: PAYMENT_WRITE does not grant reading, and reading does not grant writing.

ScopeAllows
PAYMENT_WRITECreate a charge.
PAYMENT_READGet and list charges and download the receipt.
REFUNDRefund a charge and return a deposit.
WITHDRAWWithdraw to a Pix key and pay a Pix copy-and-paste code.
WITHDRAW_READGet and list withdrawals and download the receipt.
INTERNAL_TRANSFERTransfer to another PayZu account.
INTERNAL_TRANSFER_READGet and list transfers, sent and received, and download the receipt.
DEPOSIT_READGet a Pix received without a charge and download the receipt.
STATEMENT_READGet balance, statement, limits and metrics.
PIX_KEY_READList the account's Pix keys.
PIX_KEY_WRITECreate and delete a Pix key and set the default key.
PIX_DICT_READDecode a Pix copy-and-paste code and look up the recipient.
INFRACTION_READGet MED disputes.
WEBHOOK_READList webhook endpoints and see whether the account has a callback secret.
WEBHOOK_WRITERegister, update and delete webhook endpoints and issue or rotate the callback secret.

WITHDRAW, INTERNAL_TRANSFER, REFUND, PIX_KEY_WRITE and WEBHOOK_WRITE are never selected by default in a new credential.

IP list

When the credential's IP list is filled in on the dashboard, a call from another IP receives 403 with TOKEN_IP_NOT_ALLOWED. The rule also applies to POST /oauth/token and to using the token: a token obtained from an allowed IP is refused if it comes from another one. With an empty list, any IP is accepted.

Rotation and revocation

  • The client_secret appears once, at creation. No route returns it afterwards.
  • Rotating creates a new credential, with another client_id, another client_secret and the same scopes. The previous one stays valid for 24 hours. The IP list does not carry over to the new one.
  • Revoking invalidates the credential and the tokens it issued right away.
  • Creating, rotating and revoking are done in the dashboard. The API has no route for them.

Credential rejections

They apply to every API route:

StatuscodeWhen
401TOKEN_INVALIDWrong, nonexistent or revoked credential, or expired or tampered token. Request a new token; if the rejection continues, check the credential.
401TOKEN_EXPIREDThe credential had an expiration date, and it has passed.
401JWT_INVALID_AUTH_FORMATThe Authorization header is missing, or the scheme is neither Bearer nor Basic.
401TOKEN_INVALID_AUTH_FORMATThe Basic value does not decode to client_id:client_secret.
403TOKEN_MISSING_SCOPEThe credential does not have the route's scope. details.scope says which one is missing.
403TOKEN_IP_NOT_ALLOWEDThe call came from an IP outside the credential's list.
403TOKEN_HOLDER_BLOCKEDThe account holder is blocked. The credential works again when the block is lifted.
{
  "message": "Esta credencial não tem permissão para esta operação.",
  "code": "TOKEN_MISSING_SCOPE",
  "details": { "scope": "WITHDRAW" }
}

On POST /oauth/token, a missing credential or a Basic value that does not decode responds 401 with TOKEN_INVALID. The route has two more rejections:

StatuscodeWhen
400TOKEN_UNSUPPORTED_GRANT_TYPEgrant_type is missing or different from client_credentials.
429AUTH_TOO_MANY_REQUESTSThe exchange limit per client_id and IP was exceeded. Wait for the Retry-After.

On this page