Flow to require multiple approvals before a Pix payment is executed in BaaS API.
Instead of sending a Pix payment directly, the payer creates a transaction approval request. The payment is only released after the approvers registered in the wallet cast enough approval votes.
You will need:
x-wallet-uuid header on every requestnonce header on every requestx-transaction-uuid header on every write request (create, approve, cancel, delete)Approver setup is a prerequisite managed outside this BaaS flow. Have an authorized wallet administrator provision the APPROVER and, when required, APPROVER_MASTER roles before enabling approval settings. Provision access to view the relevant requests as well as permission to vote; approval permission alone does not grant every other action in this guide.
The BaaS approval endpoints do not assign roles to wallet users. If the approvers are not configured yet, use the Users API with its required authentication and headers, including x-wallet-uuid for the same wallet used in this guide. The update must be performed by the wallet owner or an authorized wallet administrator; do not grant administrative privileges just to let a user vote. If your integration only has BaaS access, arrange this setup with the wallet administrator before enabling the approval setting.
GET /operations/permissions/types lists the available permission type tags.GET /operations/permissions/users lists wallet members and their current permission_types.PATCH /operations/permissions updates an existing member. Send user_id and permission_types, including APPROVER for common approval or APPROVER_MASTER for master approval.The submitted permission_types list replaces the member’s current roles; it does not append to them. Include the complete intended list, preserving other roles the member still needs. Confirm access to read requests separately from permission to vote or cancel. ROOT cannot be assigned, and this endpoint cannot change the wallet owner’s permissions.
graph TD
A[1: List Approval Types] --> B[2: Create Approval Setting]
B --> C[3: Decode Pix Key]
C --> D[4: Create Approval Request]
D --> E[5: Approve as Approver]
E --> F[6: Check Request State]
F --> G{State?}
G -- PENDING --> E
G -- APPROVED --> H[Payment released]
G -- CANCELED --> I[Request canceled]
G -- EXPIRED --> J[Start a new request]
Steps 1 and 2 are executed once, when configuring the wallet. Steps 3 to 6 are executed on every payment that falls under the setting.
A request is approved when the votes match the setting. Votes are counted by the permission type of the voting user, and approver_master_required decides whether master votes are counted apart.
approver_master_required |
How votes are counted | Approval condition |
|---|---|---|
false (or omitted) |
single counter — the voter’s role is not considered | total votes >= approvers_quantity |
true |
two counters — APPROVER and the wallet owner fill the common count, APPROVER_MASTER fills the master count |
common votes >= approvers_quantity and master votes >= approver_master_quantity |
Eligibility to vote is the same in both cases — APPROVER, APPROVER_MASTER, and the wallet owner. The flag changes only how the votes are counted.
How a vote is classified:
APPROVER_MASTER tag → counted as a master voteROOT)APPROVER tag → counted as a common vote403, regardless of approver_master_requiredVoting is granted to the APPROVER and APPROVER_MASTER permission types only. CLIENT and ADMIN cannot vote even when master approval is not required.
The wallet owner can vote without being assigned APPROVER. The owner’s vote counts as common unless the owner also has APPROVER_MASTER, in which case it counts only as a master vote. Each eligible user contributes at most one vote to a request.
Numeric example — setting with approvers_quantity: 2, approver_master_required: true, approver_master_quantity: 1:
| Votes cast | Common | Master | State |
|---|---|---|---|
| 2 approvers | 2 | 0 | PENDING — master vote still missing |
| 1 approver + 1 master | 1 | 1 | PENDING — one common vote still missing |
| 2 approvers + 1 master | 2 | 1 | APPROVED |
Master votes do not count toward approvers_quantity. Size the setting accordingly: the example above needs three distinct voters.
Before enabling the setting, confirm that the wallet has enough distinct eligible voters in each category. Creating the setting does not check whether the wallet currently has enough eligible voters to satisfy it. A successful creation response therefore does not guarantee that requests can receive all required votes. Count an owner with APPROVER_MASTER only toward the master requirement. Without all required votes, a request remains PENDING until canceled or expired. Use the request’s state to confirm approval; a 201 vote response alone does not confirm that all required votes were received.
GET /permissions/transaction-approval-types
List the transaction types that support the approval flow. Use it to confirm that the transaction type you want to protect is available.
Optional query params: page, size, sort, order
Returns per item: id, transaction_type_id, transaction_type_tag, description, created_at
POST /permissions/transaction-approval-settings/pix-payment
Create the rule that decides when a Pix payment of this wallet requires approval. Transaction type and currency are fixed by the endpoint — you do not send them.
Only the wallet owner can create or delete a setting. No permission type grants these two endpoints, so an APPROVER, CLIENT, or ADMIN user receives 403.
Required body:
approvers_quantity (integer, 1 to 100)min_amount (BRL cents, positive) → payments from this amount on require approvalOptional body:
approver_master_required (boolean)approver_master_quantity (integer, 1 to 100) → required when approver_master_required is true{
"approvers_quantity": 2,
"min_amount": 100000000,
"approver_master_required": true,
"approver_master_quantity": 1
}
Returns: id, created_at
Important:
approver_master_required = true without approver_master_quantity is rejectedSee Approval Rules before choosing the quantities.
DELETE /permissions/transaction-approval-settings/{id}
Settings are immutable — to change the quantities or min_amount, delete the current setting and create a new one. Wallet owner only. The request is rejected while the setting still has PENDING approval requests, so cancel or wait for them first.
POST /pix/payments/decode/by-key
Decode the destination Pix key and save the returned id. The approval request references the decoded key instead of the raw key.
POST /permissions/transaction-approval-requests/pix-payment-by-key
Create the approval request for a Pix payment by key. This replaces the direct payment call when the amount falls under an existing setting.
Required body:
decoded_pix_key_id (from Step 3)value (BRL cents, positive)Optional body:
payment_date (YYYY-MM-DD, today or later)descriptionReturns: id, render_request_body, state, created_at
Expected initial state: PENDING
Use render_request_body to display the pending payment to the approvers: it carries the payment data in a presentation-ready shape.
POST /permissions/transaction-approvals
Each approver calls this endpoint once. One call is one approval vote.
Required body:
transaction_approval_request_idReturns: id, created_at
Integration rules:
PENDING requests accept votesAPPROVED and the payment is releasedGET /permissions/transaction-approval-requests/{id}
Source of truth for the current state of the request.
Returns: id, user_name, transaction_approval_setting_id, render_request_body, amount, transaction_type_tag, state, votes, approvers_quantity, created_at
There is no webhook for transaction approvals. Poll this endpoint to follow the request.
| State | Meaning | Action |
|---|---|---|
PENDING |
Waiting for the remaining approval votes | Keep polling, or have the missing approvers call Step 5 |
APPROVED |
Every required vote was cast | Payment released. Follow it through the Pix payment endpoints |
CANCELED |
Canceled by a user of the wallet | Create a new request if the payment is still needed |
EXPIRED |
Not approved by the end of the payment date — pending requests expire on the day after their payment_date |
Create a new request |
Scheduled payments: expiration is keyed on the payment date, not on the creation date. A request created without payment_date uses the creation date, so it expires the day after it is created. A request scheduled for a future date stays PENDING and keeps accepting votes until the day after that date.
Reading votes: it is the total number of votes cast, master and common together. When approver_master_required is true, votes >= approvers_quantity alone does not mean the request is approved — use state, and GET /permissions/transaction-approvals if you need the breakdown.
DELETE /permissions/transaction-approval-requests/{id}
Cancel a request that should not be paid. This is how a payment is refused.
Cancellation requires permission for this action in the selected wallet. An authorized caller can cancel a request created by another user of that wallet. The approver role alone does not grant cancellation permission. Only PENDING requests can be canceled.
Returns: id, user_name, transaction_approval_setting_id, render_request_body, amount, transaction_type_tag, state, votes, created_at
Resulting state: CANCELED
GET /permissions/transaction-approval-types to confirm the transaction type.POST /permissions/transaction-approval-settings/pix-payment and save the returned id.POST /pix/payments/decode/by-key, then POST /permissions/transaction-approval-requests/pix-payment-by-key.POST /permissions/transaction-approvals with the request id.GET /permissions/transaction-approval-requests/{id} until APPROVED, CANCELED, or EXPIRED.GET /permissions/transaction-approval-settings/pix-payment/{id} → get one settingGET /permissions/transaction-approval-settings/pix-payment → list settings, filter by currency_symbol or transaction_type_tagGET /permissions/transaction-approval-requests → list requests, filter by state or transaction_type_tagGET /permissions/transaction-approvals → list the votes already cast, filter by transaction_approval_request_id. Each item returns user_id, user_name, wallet_id, amount, permission_type_tag, created_at — use permission_type_tag to tell master votes from common votes403:
Request not found:
GET /permissions/transaction-approval-requests/{id} returns 200 with null when no request is available in the selected wallet422 (TRANSACTION_APPROVAL_REQUEST_NOT_FOUND or TRANSACTION_APPROVAL_SETTING_NOT_FOUND)422 on create setting:
approver_master_required is true and approver_master_quantity is missingapprovers_quantity or approver_master_quantity outside 1 to 100422 on approve:
PENDING — it was already approved, canceled, or expired