Skip to main content

Transaction Approval

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.

Prerequisite

You will need:

  • an authenticated user with a finished onboarding
  • x-wallet-uuid header on every request
  • nonce header on every request
  • x-transaction-uuid header on every write request (create, approve, cancel, delete)
  • the approver users already registered in the wallet

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.

Provisioning Approvers through the Users API

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.

  1. GET /operations/permissions/types lists the available permission type tags.
  2. GET /operations/permissions/users lists wallet members and their current permission_types.
  3. 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.


Flow Overview

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.


Approval Rules

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_requiredHow votes are countedApproval condition
false (or omitted)single counter — the voter's role is not consideredtotal votes >= approvers_quantity
truetwo counters — APPROVER and the wallet owner fill the common count, APPROVER_MASTER fills the master countcommon 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:

  • user has the APPROVER_MASTER tag → counted as a master vote
  • user is the wallet owner → counted as a common vote (ROOT)
  • user has the APPROVER tag → counted as a common vote
  • none of the above → 403, regardless of approver_master_required

Voting 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 castCommonMasterState
2 approvers20PENDING — master vote still missing
1 approver + 1 master11PENDING — one common vote still missing
2 approvers + 1 master21APPROVED

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.


Step 1: List Approval Types

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


Step 2: Create the Approval Setting

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 approval

Optional 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 rejected
  • Only one setting exists per wallet, currency, and transaction type. Creating a second one is rejected
  • Settings cannot be edited. To change the quantities, delete the current setting and create a new one

See Approval Rules before choosing the quantities.

Replacing a Setting

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.


Step 3: Decode the Pix Key

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.


Step 4: Create the Approval Request

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)
  • description

Returns: 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.


Step 5: Approve the Request

POST /permissions/transaction-approvals

Each approver calls this endpoint once. One call is one approval vote.

Required body:

  • transaction_approval_request_id

Returns: id, created_at

Integration rules:

  • Authenticate each vote as the eligible user casting it. Do not use one user's credentials to represent other approvers
  • Before voting, have the approver confirm the amount and beneficiary shown in the request's API response
  • There is no reject endpoint. To refuse a payment, a user authorized to cancel requests must cancel it (Step 7)
  • Only PENDING requests accept votes
  • When the last required vote arrives, the request moves to APPROVED and the payment is released

Step 6: Check the Request State

GET /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.

StateMeaningAction
PENDINGWaiting for the remaining approval votesKeep polling, or have the missing approvers call Step 5
APPROVEDEvery required vote was castPayment released. Follow it through the Pix payment endpoints
CANCELEDCanceled by a user of the walletCreate a new request if the payment is still needed
EXPIREDNot approved by the end of the payment date — pending requests expire on the day after their payment_dateCreate 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.


Step 7: Cancel the Request

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


Minimal Integration Sequence

  1. GET /permissions/transaction-approval-types to confirm the transaction type.
  2. Confirm that the wallet users have the required approval and request access permissions (see Prerequisite).
  3. POST /permissions/transaction-approval-settings/pix-payment and save the returned id.
  4. On each payment: POST /pix/payments/decode/by-key, then POST /permissions/transaction-approval-requests/pix-payment-by-key.
  5. Each approver calls POST /permissions/transaction-approvals with the request id.
  6. Poll GET /permissions/transaction-approval-requests/{id} until APPROVED, CANCELED, or EXPIRED.

Other Endpoints

  • GET /permissions/transaction-approval-settings/pix-payment/{id} → get one setting
  • GET /permissions/transaction-approval-settings/pix-payment → list settings, filter by currency_symbol or transaction_type_tag
  • GET /permissions/transaction-approval-requests → list requests, filter by state or transaction_type_tag
  • GET /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 votes

Error Handling

403:

  • The authenticated caller lacks permission for the requested action in the selected wallet
  • Voting requires an eligible approver; reading and canceling requests require their respective permissions

Request not found:

  • GET /permissions/transaction-approval-requests/{id} returns 200 with null when no request is available in the selected wallet
  • A create, approval or cancellation operation that references a missing request or setting returns 422 (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 missing
  • approvers_quantity or approver_master_quantity outside 1 to 100

422 on approve:

  • The request is not PENDING — it was already approved, canceled, or expired