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:
Pass the token on every API call:
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.