Cumbuca Open Finance — API Reference
Reference for the Cumbuca Open Finance data-sharing API: participant directory, data-sharing consent lifecycle, Phase 2 data consumption endpoints, and the shared consent management portal.
Background — Open Finance Brasil
This section is a high-level primer for readers new to the ecosystem. If you already know how Open Finance Brasil works, jump straight to Overview.
What is Open Finance Brasil
Open Finance Brasil is a Central Bank–regulated programme that lets customers (individuals and legal entities) share their financial data across institutions in a standardised, secure way. The same idea that powered Pix's interoperability is applied to the rest of the financial stack: accounts, cards, credit, investments, and FX.
The Central Bank (BACEN) sets the rules and publishes the regulated APIs; a Deliberative Council coordinated by an industry-wide governance structure operationalises them through working groups (security, customer experience, infrastructure, etc.). Compliance is not optional — every regulated institution must expose the standard APIs in the way the spec defines.
Participation roles
Each institution joins the ecosystem under one or more roles. For data sharing, the roles split into a passive side (holds the data) and an active side (asks for the data):
| Role | Description |
|---|---|
| Transmissor de Dados passive | Typically banks; serves data requests on behalf of consented customers. |
| Receptor de Dados active | Typically fintechs / advisors; requests customer data to power their product. |
An institution can hold multiple roles simultaneously (data and payments). For this data-sharing reference, the relevant tag in the participants directory is DADOS — that's what you'll see filtered in GET /participants.
Client vs server in the protocol. The passive/active split lines up directly with the OAuth client/server split. The Receptor de Dados plays the role of OAuth client — it registers via DCR, asks for authorisation, holds the access token, and makes the API calls. The Transmissor de Dados plays the role of Authorisation Server (AS) and resource server — it authenticates the user, issues consents and tokens, and serves the regulated endpoints. So when you read "AS" in the FAPI-BR spec, picture the bank that holds the customer's data; when you read "client", picture the fintech driving the integration.
Implementation phases
The programme rolled out in four phases. The labels are still used everywhere in the spec and in conversations:
- Phase 1 — Open Data. Public, no-consent-needed information about institutions, products, rates, branches.
- Phase 2 — Customer Data. Consented sharing of customer-owned data: accounts, cards, credit operations, investments, FX. Most of the GETs you'll find under Data Consumption live here.
- Phase 3 — Services. Payment initiation and credit portability (out of scope for this reference).
- Phase 4 — Extensions. Continuous refinements to the earlier phases.
How institutions communicate
Two cross-cutting standards govern every request between institutions:
- mTLS (mutual TLS). Both sides present X.509 certificates issued by approved CAs (CertiSign, Serpro, Soluti). The TLS handshake itself is the first layer of authentication — an institution that isn't in the directory can't even open a connection.
- Message signing (JWS). Sensitive request and response bodies (such as recurring consent retrieval) are wrapped in a compact JWS — the body is a base64url
header.payload.signaturestring, signed with a separate signing certificate. This guarantees integrity end-to-end, even when the message passes through proxies.
These two combined implement the FAPI-BR security profile — a Brazilian regional flavour of OpenID Foundation's Financial-grade API standard. On top of FAPI-BR, the standard OAuth 2.0 / OIDC building blocks are used:
- DCR (Dynamic Client Registration) — institutions register their OAuth clients programmatically.
- PAR (Pushed Authorisation Request) — the authorisation request is pre-registered on the holder side, so the redirect URL the user sees is short, signed, and tamper-proof.
- OIDC redirect flow — the user is sent to the holder's bank, authenticates, authorises, and is redirected back to the initiator's
callbackApplicationUri.
For first-time integrations all of this orchestration — directory lookup, DCR, token exchange, PAR, mTLS handshake — happens for every call. It's a lot of moving parts.
Simplified request flow — putting the pieces together for a typical authorised data read:
┌─────────────────────┐ ┌──────────────────────┐
│ Customer │ │ Directory │
│ (browser / app) │ │ (Open Finance BR) │
└──────────┬──────────┘ └──────────┬───────────┘
│ │
│ 1. clicks "connect bank" │ (lists active
▼ │ participants,
┌─────────────────────┐ 0. discovery (GET list) ──────▶ certificates,
│ Client │◀────────────────────────────────┤ metadata)
│ (Receptor) │ │
│ active side │ └──────────────┘
│ ─ OAuth client ─ │
└──────────┬──────────┘
│
│ 2. DCR + PAR + consent create
│ (mTLS + JWS, over HTTPS)
▼
┌─────────────────────┐ 3. browser redirect ───────▶ ┌─────────────┐
│ Authorisation │ user authenticates & │ Customer │
│ Server (AS) │ authorises consent │ authorises │
│ Transmissor │◀───── 4. callback ───────────────│ at the AS │
│ de Dados │ └─────────────┘
│ passive side │
│ ─ OAuth server ─ │
└──────────┬──────────┘
│
│ 5. authorised API call
│ (mTLS + access token + JWS payload)
▼
┌─────────────────────┐
│ Resource server │ 6. response (JWS-signed
│ at the AS │ for sensitive endpoints)
└─────────────────────┘
Every arrow between client and AS rides on mTLS. Steps that expose private data (steps 2 and 5/6) additionally carry JWS-signed payloads. The customer's browser is only involved on steps 3 and 4 — the redirect handoff that triggers authentication and brings the user back.
Consent at the centre
Every cross-institution data read is anchored on a consent. The consent is a regulated artefact created on the holder side and tied to:
- The customer's identification document (CPF or CNPJ).
- The permissions being authorised.
- An expiration window.
- The active institution (the data receiver) that asked for it.
Until the consent is in AUTHORISED state, no protected resource can be read. After it expires, the holder will refuse the call. Picking up consent state and reacting to it — see GET /consents/v1/consents/{id} — is therefore central to any integration.
Where Cumbuca fits in
Cumbuca acts as the regulatory plumbing for institutions that want to participate as data receivers without having to build the full FAPI-BR stack in-house. The two-prefix structure you'll see throughout this reference reflects that:
/consent-management/...— Cumbuca's orchestration layer. A single HTTP call internally chains DCR → token → consent creation → PAR → redirect URL, so the integrator only deals with one request per business operation./open-finance/...— Transparent proxy to the regulated APIs. mTLS and JWS verification of responses happen inside the proxy.
The rest of this document is the API reference for those two layers.
Overview
The API surface is organized in three groups, all served under the same PARTNER_BASE_URL unless noted otherwise:
/consent-management/...— Cumbuca orchestration endpoints. Internally chain DCR → Token → Consent creation → PAR → Redirect URL, so the client only needs to call a single HTTP endpoint per business operation./open-finance/...— Transparent proxy to the regulated Open Finance Brasil APIs. mTLS, JWS request/response signing, and other regulatory plumbing are handled by the proxy.https://[sandbox.]directory.openbankingbrasil.org.br/participants— Official OF Brasil participants directory. Surfaced through the Cumbuca API as/consent-management/v1/participants.
How Access Works
Authentication to the Cumbuca API is built on two layers:
- mTLS — every connection rides on a mutually authenticated TLS handshake against the Cumbuca CA.
- Bearer access token — obtained from
POST /auth/v1/tokenand sent asAuthorization: Bearer <access_token>on every call. Required for every endpoint in this reference except the two auth endpoints themselves.
Beyond those two layers, the only piece of state the client carries from one call to the next is the consentId, which scopes the request to a specific authorised consent.
- Client calls
POST /auth/v1/tokenover mTLS with its credentials. The response carries anaccess_token, a short-livedexpires_in, and a long-livedrefresh_token. - The client sends
Authorization: Bearer <access_token>on every subsequent call. - When the access token expires, the client calls
POST /auth/v1/refreshwith the refresh token to obtain a new access token without re-submitting credentials.
- Client calls
POST /consent-management/v1/consentsover mTLS with a valid bearer token. - On
201, Cumbuca returns the regulated payload (data.consentId,data.redirectUrl,data.consent). - The client persists
data.consentIdfor later use. - User is redirected to
data.callbackApplicationUri, authorises the consent at the bank, and is redirected back.
On every subsequent call to a consent-protected endpoint (the data reads under /open-finance/... and the consent lookup itself), the client must:
- Use the same mTLS certificate as the one used to bootstrap the consent.
- Send
Authorization: Bearer <access_token>. - Send the
consentIdas thex-consent-idheader. - Send
x-authorisation-server-ididentifying the target institution.
Cumbuca verifies that the consent referenced by x-consent-id was created by the same mTLS identity making the current call, then forwards the request to the regulated API. The upstream response flows back to the client unchanged.
x-consent-id required? Every endpoint that operates on an existing consent — that is, every endpoint except GET /participants (no consent involved) and POST /consents/v1/consents (the call that creates the consent in the first place).
consentId, because the mTLS certificate on the connection won't match.
Common Headers
Every request to the partner API uses some combination of the following headers:
| Header | Required when | Value |
|---|---|---|
Authorization | Every endpoint except POST /auth/v1/token and POST /auth/v1/refresh | Bearer <access_token> obtained from the auth endpoints |
x-authorisation-server-id | Every regulated call (except auth and GET /participants) | Authorisation Server ID of the target institution (from the directory) |
x-consent-id | Phase 2 data reads | consentId returned by the consent creation call |
content-type | POSTs with a JSON body | application/json |
Error Format
The partner returns errors as JSON in the response body for any non-2xx HTTP status. The shape follows the Open Finance Brasil regulated format:
{
"errors": [
{
"code": "INVALID_REQUEST",
"title": "Validation failed",
"detail": "data.payment.amount must be a string"
}
]
}
Multiple entries in errors[] are possible when several validation failures are reported in the same response.
Callback URIs
Consent-creating endpoints accept a callbackApplicationUri in the request body. After the user authorises (or rejects) the consent on the user's bank, the bank redirects them back to that URI carrying status query parameters. Each business flow conventionally uses its own callback path so the redirect handler can route appropriately:
| Flow | Suggested callbackApplicationUri |
|---|---|
| Data sharing | https://<your-host>/consent/callback |
Quickstart — Data Sharing
End-to-end flow for reading data from a user's bank account: ask consent, pick one account, and pull its transactions.
-
Get an access token — call
POST /auth/v1/tokenwith your credentials over mTLS. Keep the returnedaccess_tokenfor the calls below, and therefresh_tokenfor when the access token expires (usePOST /auth/v1/refresh). Every call from here on must carryAuthorization: Bearer <access_token>. -
Pick the user's bank — call
GET /consent-management/v1/participantsand filter by theDADOSrole. Capture the chosenauthorisationServerId. -
Create the data-sharing consent — call
POST /consent-management/v1/consentswith the user's document and the permissions you need (at minimumACCOUNTS_READ,ACCOUNTS_TRANSACTIONS_READ, andRESOURCES_READ). You'll get back aconsentIdand aredirectUrl. -
Send the user to the bank — redirect the browser to the returned
redirectUrl. The user authenticates and authorises the sharing on the bank's site, then is redirected back to yourcallbackApplicationUri. -
Confirm the consent is authorised — when the callback hits, call
GET /consent-management/v1/consents/{consentId}and checkstatus == "AUTHORISED". If it'sREJECTED, stop here and show an error. -
List the user's accounts — call
GET /open-finance/accounts/v2/accountswith the authorisedconsentIdin thex-consent-idheader. Pick theaccountIdyou want to read from (e.g. the first checking account). -
Read the transactions — call
GET /open-finance/accounts/v2/accounts/{accountId}/transactionsusing the same headers. The response contains the transaction history underdata[].
Authentication
All endpoints in this reference (except the two below) require an Authorization: Bearer <access_token> header. Access tokens are short-lived; long-lived refresh tokens let the client renew them without re-exchanging credentials.
POST/auth/v1/token
Exchanges client credentials for an access token and a refresh token.
content-type | required application/json |
{
"client_id": "<your-client-id>",
"client_secret": "<your-client-secret>"
}
{
"access_token": "eyJhbGciOi...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "eyJhbGciOi..."
}
POST/auth/v1/refresh
Exchanges a refresh token for a new access token (and a new refresh token).
content-type | required application/json |
{
"refresh_token": "<your-refresh-token>"
}
{
"access_token": "eyJhbGciOi...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "eyJhbGciOi..."
}
Directory
GET/consent-management/v1/participants
Returns all institutions registered in the Open Finance Brasil participants directory. Clients should filter by the roles they care about — typically DADOS (data) and CONTA (payments) — and by claim Status == "Active".
Authorization | required Bearer <access_token> |
[
{
"CustomerFriendlyName": "Banco X",
"CustomerFriendlyLogoUri": "https://...",
"AuthorisationServerIds": ["asid-uuid"],
"OrgDomainRoleClaims": [
{ "Role": "DADOS", "Status": "Active" },
{ "Role": "CONTA", "Status": "Active" }
],
"ApiResources": [{ "ApiFamilyType": "accounts" }],
"Organisations": [{ "RegisteredName": "BANCO X S.A." }]
}
]
Data Sharing Consent
POST/consent-management/v1/consents
Creates a data-sharing consent (Phase 2). Returns a consentId and a redirectUrl the end user must be redirected to in order to authorise the consent at the data-holding bank.
Authorization | required Bearer <access_token> |
x-authorisation-server-id | required |
{
"data": {
"callbackApplicationUri": "https://.../consent/callback",
"loggedUser": {
"document": { "identification": "12345678901", "rel": "CPF" }
},
"businessEntity": { // optional — when the logged user acts as a legal-entity representative
"document": { "identification": "12345678000199", "rel": "CNPJ" }
},
"permissions": [
"ACCOUNTS_READ", "ACCOUNTS_BALANCES_READ",
"RESOURCES_READ"
],
"expirationDateTime": "2026-05-28T15:10:00Z"
}
}
| Field | Type | Notes |
|---|---|---|
data.callbackApplicationUri | string | required Absolute URI |
data.loggedUser.document.identification | string | required CPF or CNPJ (digits only) |
data.loggedUser.document.rel | enum | required "CPF" or "CNPJ" |
data.businessEntity | object | optional Present when the logged user represents a legal entity |
data.permissions | string[] | required Regulated OF permission strings; see appendix |
data.expirationDateTime | ISO 8601 | required Maximum lifetime of the consent |
{
"data": {
"consentId": "urn:cumbuca:C123ABC...",
"redirectUrl": "https://auth.bank.example/oauth2/authorize?..."
}
}
GET/consent-management/v1/consents/{consentId}
Returns the current state of a data-sharing consent: status (AWAITING_AUTHORISATION, AUTHORISED, REJECTED, CONSUMED), permissions, and expiration. Useful for polling after the user is redirected back from the bank, and for displaying consent state in management screens.
consentId | required ID returned by the consent creation call |
Authorization | required Bearer <access_token> |
x-authorisation-server-id | required |
{
"data": {
"consentId": "urn:raidiambank:c4bb1a06-8dcf-4935-9696-b40bf6911f50",
"consent": {
"data": {
"consentId": "urn:raidiambank:c4bb1a06-...",
"status": "AUTHORISED",
"creationDateTime": "2026-01-29T16:34:29Z",
"statusUpdateDateTime": "2026-01-29T16:34:41Z",
"expirationDateTime": "2026-07-29T16:34:27Z",
"permissions": ["ACCOUNTS_READ", "ACCOUNTS_BALANCES_READ", "RESOURCES_READ"]
},
"links": { "self": "https://matls-api.<bank>/open-finance/consents/v3/consents/<consentId>" },
"meta": { "requestDateTime": "2026-01-29T16:35:00Z" }
}
}
}
data.consent is the verbatim regulated payload returned by the data-holding bank (with its own data / links / meta sections per the OF Brasil spec), and the outer data.consentId is a convenience field added by the orchestration layer so callers don't have to dig into data.consent.data.consentId.
Data Consumption (Phase 2) — Authenticated GETs
All endpoints in this section follow the same shape:
- Method: GET
- Headers:
Authorization: Bearer <access_token>,x-authorisation-server-id,x-consent-id - Response:
{ "data": [...] }— regulated OF Brasil format - Retries: data reads are billable and may have rate limits; treat them as non-idempotent for retry purposes.
Customers
| Endpoint | Notes |
|---|---|
GET /open-finance/customers/v2/personal/identifications | Natural person identification |
GET /open-finance/customers/v2/business/identifications | Legal entity identification |
GET /open-finance/customers/v2/personal/financial-relations | Personal financial relationships |
GET /open-finance/customers/v2/business/financial-relations | Business financial relationships |
GET /open-finance/customers/v2/personal/qualifications | Personal qualifications (income, etc.) |
GET /open-finance/customers/v2/business/qualifications | Business qualifications |
Accounts (Checking / Savings)
| Endpoint | Notes |
|---|---|
GET /open-finance/accounts/v2/accounts | List accounts |
GET /open-finance/accounts/v2/accounts/{accountId} | Account details |
GET /open-finance/accounts/v2/accounts/{accountId}/balances | Balances |
GET /open-finance/accounts/v2/accounts/{accountId}/overdraft-limits | Overdraft limits |
GET /open-finance/accounts/v2/accounts/{accountId}/transactions | Transactions |
Credit Cards
| Endpoint | Notes |
|---|---|
GET /open-finance/credit-cards-accounts/v2/accounts | List card accounts |
GET /open-finance/credit-cards-accounts/v2/accounts/{id} | Card account details |
GET /open-finance/credit-cards-accounts/v2/accounts/{id}/bills | Bills |
GET /open-finance/credit-cards-accounts/v2/accounts/{id}/bills/{billId}/transactions | Bill transactions |
GET /open-finance/credit-cards-accounts/v2/accounts/{id}/limits | Card limits |
GET /open-finance/credit-cards-accounts/v2/accounts/{id}/transactions | Card transactions |
Credit Operations (4 families)
Generic shape for the scopes loans, financings, invoice-financings, and unarranged-accounts-overdraft:
Endpoint (with {scope}) | Notes |
|---|---|
GET /open-finance/{scope}/v2/contracts | List contracts |
GET /open-finance/{scope}/v2/contracts/{contractId} | Contract details |
GET /open-finance/{scope}/v2/contracts/{contractId}/payments | Payment history |
GET /open-finance/{scope}/v2/contracts/{contractId}/scheduled-instalments | Scheduled instalments |
GET /open-finance/{scope}/v2/contracts/{contractId}/warranties | Collateral / warranties |
Investments (5 families)
Scopes: bank-fixed-incomes, credit-fixed-incomes, variable-incomes, treasure-titles, funds.
| Endpoint | Notes |
|---|---|
GET /open-finance/{scope}/v1/investments | List investments |
GET /open-finance/{scope}/v1/investments/{id} | Investment details |
GET /open-finance/{scope}/v1/investments/{id}/balances | Balances |
GET /open-finance/{scope}/v1/investments/{id}/transactions | Historical transactions |
GET /open-finance/{scope}/v1/investments/{id}/transactions-current | Current-period transactions |
Exchanges (FX)
| Endpoint | Notes |
|---|---|
GET /open-finance/exchanges/v1/operations | List FX operations |
GET /open-finance/exchanges/v1/operations/{operationId} | Operation details |
GET /open-finance/exchanges/v1/operations/{operationId}/events | Operation events |
Resources (discovery)
| Endpoint | Notes |
|---|---|
GET /open-finance/resources/v3/resources | Lists every resource the consent grants access to |
Consent Management
Lets the end user view, manage, and revoke all the consents they've authorised for the client. The call returns a one-time URL — redirect the user there to open the management portal.
POST/consent-management/v1/management
Returns a one-time URL with an embedded session token. Redirect the end user to that URL to access the consent management portal.
Authorization | required Bearer <access_token> |
content-type | required application/json |
{
"document": "12345678901",
"representativeCpf": "98765432100"
}
| Field | Type | Notes |
|---|---|---|
document | string | required The end user's CPF (11 digits) or CNPJ (14 digits) |
representativeCpf | string | optional The representative's CPF — only used when document is a CNPJ and a legal-entity representative is acting on behalf of the company |
{
"redirectUrl": "https://.../management/?token=..."
}
Appendix
Category → OF permission mapping
Open Finance Brasil defines ~30 granular permission strings. Most clients group them into a small set of user-facing categories. RESOURCES_READ should always be included when creating a data-sharing consent.
| Category | Permissions to request |
|---|---|
customers (natural person) | CUSTOMERS_PERSONAL_IDENTIFICATIONS_READ, CUSTOMERS_PERSONAL_ADITTIONALINFO_READ |
customers (legal entity) | CUSTOMERS_BUSINESS_IDENTIFICATIONS_READ, CUSTOMERS_BUSINESS_ADITTIONALINFO_READ |
accounts | ACCOUNTS_READ, ACCOUNTS_BALANCES_READ, ACCOUNTS_TRANSACTIONS_READ, ACCOUNTS_OVERDRAFT_LIMITS_READ |
credit_cards | CREDIT_CARDS_ACCOUNTS_READ, ..._BILLS_READ, ..._BILLS_TRANSACTIONS_READ, ..._LIMITS_READ, ..._TRANSACTIONS_READ |
invoice_financings | INVOICE_FINANCINGS_READ, ..._PAYMENTS_READ, ..._SCHEDULED_INSTALMENTS_READ, ..._WARRANTIES_READ |
financings | FINANCINGS_READ, ..._PAYMENTS_READ, ..._SCHEDULED_INSTALMENTS_READ, ..._WARRANTIES_READ |
loans | LOANS_READ, ..._PAYMENTS_READ, ..._SCHEDULED_INSTALMENTS_READ, ..._WARRANTIES_READ |
unarranged_overdraft | UNARRANGED_ACCOUNTS_OVERDRAFT_READ, ..._PAYMENTS_READ, ..._SCHEDULED_INSTALMENTS_READ, ..._WARRANTIES_READ |
bank_fixed_incomes | BANK_FIXED_INCOMES_READ |
credit_fixed_incomes | CREDIT_FIXED_INCOMES_READ |
variable_incomes | VARIABLE_INCOMES_READ |
treasure_titles | TREASURE_TITLES_READ |
funds | FUNDS_READ |
exchanges | EXCHANGES_READ |
| (always) | RESOURCES_READ |