Skip to main content

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 the Authorization header of every request.

1. Get your credentials

Create an API credential in the Dashboard. It consists of a client_id and a client_secret:
  • mp_live_*production credential
  • mp_test_*sandbox credential
The client_secret is shown only once, at creation time. Store it somewhere safe.

2. Generate an access token

Exchange your credentials for a token at the authentication endpoint:
Response
Invalid or revoked credentials return 401 {"error": "Unauthorized", "message": "Invalid credentials"}.

3. Use the token in your requests

Send the token in the Authorization 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 a 403 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 a reference 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:
The header is optional and is accepted on every endpoint except /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

The X-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.
The wallet has to be created in each environment. Creating 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 R20.00andsharingR 20.00 and sharing R 1.00 ends at +R18.80ontheoriginatorand+R 18.80** on the originator and **+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.
What to know before transferring:
  • 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.
In the statement, each transfer produces two lines of type 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.
Creating wallets does not multiply your limit. Since there is a single budget, a charge on one wallet can be refused for limit because of the movement of another wallet in the same account — including a wallet your code did not touch in that request. That is the expected behavior, not a broken isolation.
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 the SUB_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-accounts endpoints: listing requires SUBACCOUNT:READ, creating requires SUBACCOUNT:WRITE. Without it, the response is 403 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-Account header and the split, and it is what returns SUB_ACCOUNT_FORBIDDEN.
That is why creating a charge with X-Sub-Account and split only requires PIX:WRITE: the SUBACCOUNT:* permissions govern the registry of wallets, not their use.
The scope starts turned off, and no permission replaces it. A newly created credential — even one with full access — gets 403 SUB_ACCOUNT_FORBIDDEN on its first request carrying X-Sub-Account while the scope is set to “no access”. Turn it on under Settings → Integration → API Credentials, in the Sub-account access field (it takes effect immediately, including for tokens already issued). This is deliberate: without it, every credential that already existed would reach the whole tree the day the first wallet was created.
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 optional split 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 the X-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 R100.00chargewithaR 100.00** charge with a **R 1.49 fee, the net is **R98.51andthatisthecap.AsplitaddinguptoR 98.51** — and that is the cap. A `split` adding up to R 98.51 is accepted (the originator keeps zero). A split adding up to **R99.00isrejected,eventhoughitislessthantheR 99.00** is rejected, even though it is less than the R 100.00 of the charge:
400 response
The fee taken into account is the one of the account originating the charge, for the PIX method.
Refunds and MED hit the originator only. Whoever received a share is never debited: there is no cascading refund and no clawback of money already passed on. A refund, a chargeback or a MED block on the charge debits exclusively the account that originated it.The consequence is yours to manage: if you split 100% of the net amount and the transaction is refunded, the originator absorbs the entire loss — and the debit may leave its balance negative. Keeping a margin in the originator is the integrator’s decision, not the system’s.

The split happens at settlement

Creating the charge moves no money at all. The split 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:
With a R0.20fee,theresultis:lojacentrokeepsR 0.20 fee, the result is: `loja-centro` keeps **R 14.80** (R20.00minustheR 20.00 minus the R 0.20 fee minus the R5.00share)andthemainaccountreceivesR 5.00 share) and the main account receives **R 5.00**. The originator is still 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.
To move balance between wallets outside of a payment, use the internal transfer — an explicit operation, not attached to the settlement of a charge.

Splitting from a sub-account

The X-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 R100.00,paysthefeeandpassesR 100.00, pays the fee and passes R 20.00 on to loja-sul. A sub-account cannot split with itself.

Split errors

All of them return 400. The messages are returned by the API exactly as shown:

In the statement

At settlement, each split leg produces two lines of type internal_transfer, both tied to the charge by parentTransactionId:
  • an outgoing line on the originator — Split enviado para loja-centro, or Split enviado para a conta principal when the destination is principal
  • an incoming line on the receiving wallet — Split recebido do pagamento {charge id}
Both are real transactions: Get Transaction returns 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 sending pspCredentialId when creating the charge:
Without the field nothing changes: the configured routing still applies, with failover.

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 send pspCredentialId, 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 echoes pspCredentialId 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

All 400, 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