Skip to content

Credentials & Authentication

QPay uses OAuth2 client credentials for machine-to-machine API authentication. Your application exchanges a client_id and client_secret for a short-lived JWT access token, which it includes on every API request.

Prerequisites

You must have completed Step 1 and Step 2 of the developer guide — your tenant exists and you have logged in at least once to set your password.


Creating client credentials

Client credentials are created via the Credentials API. You authenticate to this API with your personal user token (not a client credential) to bootstrap the first credential.

1. Sign in and get a user token

Authenticate with your username and password using the OAuth2 password grant:

curl -X POST https://sandbox.qpay.quecto.com.br/realms/qpay/protocol/openid-connect/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=password" \
  -d "client_id=qpay-console" \
  -d "username=YOUR_USERNAME" \
  -d "password=YOUR_PASSWORD"

Save the access_token from the response. It is valid for 5 minutes.

2. Find your tenant ID

curl https://sandbox.qpay.quecto.com.br/api/credentials/whoami \
  -H "Authorization: Bearer <access_token>"

Response:

{
  "tenant_type": "issuer",
  "tenant_id": "your-tenant-id",
  "parent_tenant_id": "parent-processor-tenant-id"
}

Save the tenant_id — you will need it in the next step.

3. Create a client

curl -X POST https://sandbox.qpay.quecto.com.br/api/credentials/clients \
  -H "Authorization: Bearer <access_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "tenant_id": "your-tenant-id",
    "name": "my-integration-client",
    "roles": ["issuer"]
  }'

Response:

{
  "id": "internal-record-id",
  "client_id": "abc123...",
  "client_secret": "supersecret...",
  "tenant_id": "your-tenant-id"
}

Save the secret now

The client_secret is only returned once, at creation time. Store it securely — it cannot be retrieved again. If lost, delete the client and create a new one.


Obtaining an access token

Once you have a client_id and client_secret, your application obtains tokens autonomously using the OAuth2 client credentials grant — no user interaction required:

curl -X POST https://sandbox.qpay.quecto.com.br/realms/qpay/protocol/openid-connect/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials" \
  -d "client_id=YOUR_CLIENT_ID" \
  -d "client_secret=YOUR_CLIENT_SECRET"

Response:

{
  "access_token": "eyJhbGci...",
  "expires_in": 300,
  "token_type": "Bearer"
}

Pass the token on every API call:

Authorization: Bearer eyJhbGci...

Token expiry

Tokens expire after 300 seconds (5 minutes). Your application should request a new token before the current one expires. A simple strategy is to re-fetch a token before each API call or cache it and refresh when expires_in - 30 seconds have elapsed.


Managing credentials

List your clients

curl https://sandbox.qpay.quecto.com.br/api/credentials/clients/{id} \
  -H "Authorization: Bearer <access_token>"

Update client roles

curl -X PUT https://sandbox.qpay.quecto.com.br/api/credentials/clients/{id} \
  -H "Authorization: Bearer <access_token>" \
  -H "Content-Type: application/json" \
  -d '{"roles": ["issuer"]}'

Delete a client

curl -X DELETE https://sandbox.qpay.quecto.com.br/api/credentials/clients/{id} \
  -H "Authorization: Bearer <access_token>"

Available roles

The roles available to your client depend on your tenant type. Query the roles endpoint to see what your tenant can assign:

curl https://sandbox.qpay.quecto.com.br/api/credentials/roles \
  -H "Authorization: Bearer <access_token>"
Tenant type Typical roles Access
processor processor BINs, templates, issuers, dashboard
issuer issuer Cards, products, layouts, certificates
embosser embosser Pending embossing jobs, card status updates

Product, layout and card roles

Card issuance is gated the same way: fine-grained, issuer-scoped roles, each with a manage-* superset and narrower verbs beneath it. A client holding manage-product, manage-layout and manage-card can run the whole flow; grant less where the job is narrower.

Setting up an offering — see Manage Card Products:

Role Grants
request-processor-membership Ask a processor to work with this issuer
view-processor-membership Read which processors you work with, and the state of pending requests
create-product Create a product, and list the card templates available to build one on
view-product Read products, their layouts and embosser links, and the issuing-data listing
update-product Rename or deactivate a product; add, approve, remove and reorder a layout's embossers
delete-product Delete a product that has never issued a card
manage-product All of the above, plus exporting the product parameters
create-layout Add a layout to a product
view-layout Read layouts, their graphic specifications, previews and the geometry catalogue
update-layout Change a layout; upload artwork and write its graphic specification
delete-layout Remove a layout
manage-layout All of the above

Issuing and running cards — see Create a Card:

Role Grants
create-card Issue cards, singly or in batch; import and manage issuer certificates
view-card Read cards and their applications
manage-card All of the above, plus adding and removing card blocks — blocking is manage-card only
create-card, update-card, view-card or manage-card Authorization rules, at both issuer and card level — any one of the four
reveal-card-data Read a card's PAN, CVV and expiry in the clear
reveal-pin Reconstruct a cardholder's PIN — kept separate from reveal-card-data and update-pin as the most sensitive of the three
update-pin Set a new PIN on a card

The broad issuer role is not enough

The issuer role in the table above establishes tenant type; it does not imply any of the roles here. A client created without them gets 403 on every product, layout and card endpoint.

Ledger roles

Ledger operations are gated by their own fine-grained roles, all issuer-scoped. They are not implied by the broad issuer role — assign them explicitly to the client that needs them.

Configuring where QPay sends authorization — see Connect Your Own Ledger:

Role Grants
manage-ledger-callback Register the callback base URL, import the TLS trust anchor, rotate the signing secret
view-ledger-callback Read the callback configuration without being able to change it

Using QPay's internal ledger — see Use the QPay Ledger:

Role Grants
manage-ledger-tenant Join the ledger, activate currencies, read your own membership
manage-ledger-pool Record money arriving in or leaving your physical bank account
manage-ledger-cardholder Create, list and update cardholders; read balances and credit limits
approve-ledger-kyc Approve a cardholder's KYC for a currency, creating their checking account
deposit-ledger-funds Credit a cardholder's checking account
create-ledger-card Create a card and its credit accounts
manage-ledger-credit-limit Change a card's granted credit limit after issuance

Credit invoicing — see Run a Billing Cycle:

Role Grants
manage-ledger-invoice Configure billing cycles; close statements, accrue finance charges, run reconciliation
view-ledger-invoice Read statements and their lines without being able to run the jobs
register-ledger-payment Record and apply a cardholder's invoice payment

Why these are separate roles

Each one moves a different kind of money, so they map to different job functions. manage-ledger-pool mirrors real bank movement for the whole tenant — a treasury act, not a back-office one. deposit-ledger-funds credits a prepaid balance, which is why it is not folded into manage-ledger-cardholder. register-ledger-payment settles credit debt rather than funding a wallet. Granting the narrowest role that fits keeps a compromised client from moving money it was never meant to touch.


Full Credentials API reference

See the Credentials API for the complete endpoint reference.