Welcome
The pague.dev API lets you integrate payment processing into your applications. This documentation covers all the endpoints available to manage customers, projects, charges, transactions, and PIX payments.Base URL
All requests must be made to:Authentication
Authentication happens in two steps: you exchange your account credentials for a short-lived access token and send that token in theAuthorization header of every request.
1. Get your credentials
Create an API credential in the Dashboard. It consists of aclient_id and a client_secret:
mp_live_*— production credentialmp_test_*— sandbox credential
2. Generate an access token
Exchange your credentials for a token at the authentication endpoint:Response
401 {"error": "Unauthorized", "message": "Invalid credentials"}.
3. Use the token in your requests
Send the token in theAuthorization header:
The token expires in 300 seconds (5 minutes). Generate a new token at
/auth when it expires — there is no refresh token.Permissions
Each credential has granular permissions that determine which endpoints it can access. Permissions are assigned when the credential is created.Available permissions
The
FULL_ACCESS permission grants access to all endpoints, equivalent to holding every permission listed above.Exception: sub-account access is not a permission. FULL_ACCESS covers the /sub-accounts endpoints (creating and listing wallets), but it does not enable the X-Sub-Account header — that is a separate field on the credential. See Sub-accounts.IP restriction
Optionally, you can restrict a credential to a list of allowed IPs. When the list is configured, requests originating from IPs outside of it are rejected with a403 Forbidden error.
We recommend configuring IP restriction on credentials with sensitive permissions, such as FULL_ACCESS and WITHDRAWAL:WRITE.
Sub-accounts
An account can have sub-accounts: child wallets whose balance is fully independent from the main account balance. Each sub-account is identified by areference you choose.
Sub-accounts and split work in both environments: an mp_test_* credential creates and operates wallets in the sandbox just like an mp_live_* one does in production.
To operate on a sub-account, send the X-Sub-Account header with its reference:
/auth and the /sub-accounts endpoints themselves — creating and listing sub-accounts always happens on the main account. When present, the whole operation happens on the sub-account — creating a charge, retrieving a transaction, creating a withdrawal, checking the balance. When omitted, the operation happens on the main account. X-Sub-Account: principal also resolves to the main account, and is equivalent to omitting the header.
The
reference is defined by you when the sub-account is created and is immutable. It must match ^[a-z0-9][a-z0-9_-]{1,31}$: 2 to 32 characters, only lowercase letters, digits, - and _, starting with a lowercase letter or a digit.principal is a reserved word: it identifies the main account in the split and in the X-Sub-Account header, so no sub-account can be created with that reference.Sub-accounts in the sandbox
TheX-Sub-Account header, the split, the principal keyword and the internal transfer work in the sandbox exactly as they do in production.
The same reference can exist in both environments. The sandbox account and the production account are distinct accounts, so loja-centro in the sandbox and loja-centro in production coexist without colliding. That is what lets the same payload run in both: you test with mp_test_*, swap the key for an mp_live_* one and go to production without changing a line.
The two trees are isolated. An
mp_test_* credential only sees the wallets of the sandbox tree; an mp_live_* one, only those of production.This applies to the split: sharing from a sandbox wallet to a production wallet is refused, because the production one does not exist in that context. The error is the same Subconta 'X' não existe nesta conta ou não está ativa.loja-centro in production does not make it appear in the sandbox — they are two separate registrations, on purpose.
The fee is the same in both environments, and that is deliberate: the sandbox wallet inherits the fee of the production account precisely so that the split cap, which is the net amount and not the gross, behaves the same. A split that passes in the sandbox passes in production. A sandbox wallet originating R 1.00 ends at +R 1.00 on the destination, with a R$ 0.20 fee — the same numbers as production.
Internal transfer
A sub-account starts with a zero balance. The internal transfer is how you fund a new wallet — and how you send balance back to the main account later. It moves balance between accounts under the same ownership: from the main account to a wallet, from a wallet to the main account, or between sibling wallets. It is not PIX and it is not a withdrawal — it is moving money between your own pockets. The money leaves one account and enters the other, shows up in both statements, and the total balance of the account does not change.There is no internal transfer endpoint in the public API. The operation is done in the Dashboard, on the wallets screen. There is no route to look for: it is not part of this contract.
- Same ownership only. Transferring to someone else’s account does not exist here — that is PIX, and the path is Create PIX Withdrawal.
- The cap is the spendable balance of the source, not the raw available balance: it is the available balance minus any open refund debt, the same criterion used for withdrawals.
- There is no undo. A wrong transfer is corrected by transferring back in the opposite direction.
internal_transfer — an outgoing one (negative amount) on the source and an incoming one (positive) on the destination. It is the same type as the split legs: in both cases, GET /transactions/{id} returns type: internal_transfer.
Sub-account limits
By default, a wallet shares the limit budget of the main account. That is the behavior of every sub-account created through the API or the panel: the usage of all wallets adds up against the same ceiling of the account holder. The platform can, case by case, give a wallet its own budget, separating its usage from the rest of the account. That is a platform decision: it is not configurable by the merchant, it has no endpoint and it is not self-service — if your operation needs it, talk to support. There is no limit in the sandbox: the shared ceiling described here only shows up in production. That is not specific to wallets — it applies to any sandbox operation — so do not conclude from your tests that the sharing is gone. Do not confuse it with theSUB_ACCOUNT_QUOTA_EXCEEDED in the table below: that one is the ceiling on how many wallets the account can have, and has nothing to do with transacted amounts.
Sub-account errors
Two different things control access to wallets, and they fail in different ways:
- The credential’s permission applies to the
/sub-accountsendpoints: listing requiresSUBACCOUNT:READ, creating requiresSUBACCOUNT:WRITE. Without it, the response is403 Insufficient permissions. Required: SUBACCOUNT:READ. - The credential’s scope applies to operating inside a wallet: it decides which wallets that credential can reach through the
X-Sub-Accountheader and thesplit, and it is what returnsSUB_ACCOUNT_FORBIDDEN.
X-Sub-Account and split only requires PIX:WRITE: the SUBACCOUNT:* permissions govern the registry of wallets, not their use.
Sub-accounts are created at Create Sub-account and listed at List Sub-accounts. In webhooks, the subAccount field tells which wallet the event belongs to — see Webhooks.
Payment Split
A PIX charge can split part of the amount it receives with other wallets of the same account — sub-accounts or the main account itself. Send the optionalsplit field when creating the charge:
Amounts are fixed, in BRL: there is no percentage split. The creation response echoes the accepted
split back, in the same format and also in BRL — if it came back in the response, the sub-accounts existed and the sum fit. Validation happens before the charge is generated: an invalid split returns 400 and no charge is created.
Whoever creates the charge is the originator
The originator is the account — or the sub-account in theX-Sub-Account header — that created the charge. It is the one that receives the gross amount, pays the full fee, and only then splits what is left.
The fee is not split across the recipients. Each sub-account in the split receives exactly the amount you asked for, with nothing deducted.
The cap is the net amount, not the gross
The most that can be split is the charge amount minus the fee. On a R 1.49 fee, the net is **R 98.51 is accepted (the originator keeps zero). Asplit adding up to **R 100.00 of the charge:
400 response
The split happens at settlement
Creating the charge moves no money at all. Thesplit is recorded on the charge and is only executed when the payment is confirmed — that is when the amounts leave the originator’s balance and enter the destination wallets. A charge that expires or is never paid produces no split.
The account’s fee can change between the creation of the charge and the payment. If, at settlement, the
split sum no longer fits in the net amount, the legs are honored in the order you sent them, until the net runs out: the last one may be reduced, or may not happen at all. Settlement never fails because of this — order the array by priority and reconcile using the split of the payment_completed webhook, which carries what was actually distributed.Only wallets of the same account
subAccount accepts the reference of an active sub-account of the same account, or the reserved word principal. Splitting outside the ownership does not exist in this API.
Splitting back to the main account
principal is the one word that is nobody’s reference: it addresses the main account as the destination of the share. It covers the reverse path from the rest of this section — the charge is born in a sub-account and part of the net amount goes back to the main account:
loja-centro — it is the one paying the full fee, and the main account receives a clean share, like any other recipient.
The echo in the response and the split in the webhook carry "subAccount": "principal", just like the other wallets.
A charge originated by the main account cannot split to
principal — that would be splitting with itself, and whatever is not split already stays there anyway. That case returns 400.Splitting from a sub-account
TheX-Sub-Account header and the split field answer different questions and work together: the header says who originates the charge, the split says who gets part of the net amount.
A sub-account can originate a charge and split it with a sibling. In that case the main account is not touched — it receives nothing and pays no fee:
loja-centro is the originator: it receives the R 20.00 on to loja-sul. A sub-account cannot split with itself.
Split errors
All of them return400. The messages are returned by the API exactly as shown:
In the statement
At settlement, each split leg produces two lines of typeinternal_transfer, both tied to the charge by parentTransactionId:
- an outgoing line on the originator —
Split enviado para loja-centro, orSplit enviado para a conta principalwhen the destination isprincipal - an incoming line on the receiving wallet —
Split recebido do pagamento {charge id}
type: internal_transfer for each of them. The parentTransactionId is a statement-level link and is not part of the public response.
Choosing the Institution
Every PIX charge is issued by one of the institutions linked to your account. By default the pick is made by the routing configured in the dashboard — fixed order, split by shares, or automatic. If your account has institution choice enabled, you can decide it per charge by sendingpspCredentialId when creating the charge:
Where to find the ID
In the dashboard, under Settings → Routing. Each institution shows its ID right below the numbers, with a copy button. It lives there rather than in a separate list on purpose: on that same row you see the last 6 hours’ conversion, the 7- and 30-day closes and whether the institution is responding. Picking an institution without those numbers is picking blind. The ID is stable: it does not change when you reorder institutions, switch modes or disable another one.Pinning is not preferring
When you sendpspCredentialId, the charge is issued by that institution or not at all. There is no fallback:
In neither case is the charge created at a different institution.
This is deliberate. Falling back would have the QR born somewhere you did not ask for, and you would only find out by reading the response — which is worse than failing, precisely for whoever pins an institution for reconciliation, limits or contract reasons. If you prefer conversion over predictability, don’t send the field: that is what routing with failover is for.
Receipt in the response
If you pinned the institution, the response echoespspCredentialId with the one that actually issued the charge — use it for reconciliation. Without the field in the request, it is absent from the response too.
201 Response
Institution choice errors
All400, with the code in reason:
Validation happens before any call to the institution: a rejection here never leaves a charge hanging.
The choice applies to PIX charges only. Withdrawals still go out through the institution set for withdrawals — that pick stays ours, because it is the same one that pays fees and refunds.
Available Resources
PIX
Create PIX charges
Webhooks
Receive event notifications
Projects
Organize payments by project
Withdrawals
Create PIX withdrawals
Transactions
View transaction details
Account
Check account details and balance
Sub-accounts
Child wallets with their own balance

