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):

RoleDescription
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:

How institutions communicate

Two cross-cutting standards govern every request between institutions:

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:

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.

Every cross-institution data read is anchored on a consent. The consent is a regulated artefact created on the holder side and tied to:

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:

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.
Environments: Two directories are exposed — sandbox and production — selected via configuration. Sandbox should be used for conformance suite testing and all non-production traffic.

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/token and sent as Authorization: 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.

Obtaining an access token
  1. Client calls POST /auth/v1/token over mTLS with its credentials. The response carries an access_token, a short-lived expires_in, and a long-lived refresh_token.
  2. The client sends Authorization: Bearer <access_token> on every subsequent call.
  3. When the access token expires, the client calls POST /auth/v1/refresh with the refresh token to obtain a new access token without re-submitting credentials.
Bootstrapping a consent
  1. Client calls POST /consent-management/v1/consents over mTLS with a valid bearer token.
  2. On 201, Cumbuca returns the regulated payload (data.consentId, data.redirectUrl, data.consent).
  3. The client persists data.consentId for later use.
  4. User is redirected to data.callbackApplicationUri, authorises the consent at the bank, and is redirected back.
Calling protected resources

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 consentId as the x-consent-id header.
  • Send x-authorisation-server-id identifying 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.

When is 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).
Why this matters: consents are pinned to the mTLS identity that created them. A client can't read another client's consent, even if it somehow learns the 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:

HeaderRequired whenValue
AuthorizationEvery endpoint except POST /auth/v1/token and POST /auth/v1/refreshBearer <access_token> obtained from the auth endpoints
x-authorisation-server-idEvery regulated call (except auth and GET /participants)Authorisation Server ID of the target institution (from the directory)
x-consent-idPhase 2 data readsconsentId returned by the consent creation call
content-typePOSTs with a JSON bodyapplication/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:

FlowSuggested callbackApplicationUri
Data sharinghttps://<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.

  1. Get an access token — call POST /auth/v1/token with your credentials over mTLS. Keep the returned access_token for the calls below, and the refresh_token for when the access token expires (use POST /auth/v1/refresh). Every call from here on must carry Authorization: Bearer <access_token>.
  2. Pick the user's bank — call GET /consent-management/v1/participants and filter by the DADOS role. Capture the chosen authorisationServerId.
  3. Create the data-sharing consent — call POST /consent-management/v1/consents with the user's document and the permissions you need (at minimum ACCOUNTS_READ, ACCOUNTS_TRANSACTIONS_READ, and RESOURCES_READ). You'll get back a consentId and a redirectUrl.
  4. 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 your callbackApplicationUri.
  5. Confirm the consent is authorised — when the callback hits, call GET /consent-management/v1/consents/{consentId} and check status == "AUTHORISED". If it's REJECTED, stop here and show an error.
  6. List the user's accounts — call GET /open-finance/accounts/v2/accounts with the authorised consentId in the x-consent-id header. Pick the accountId you want to read from (e.g. the first checking account).
  7. Read the transactions — call GET /open-finance/accounts/v2/accounts/{accountId}/transactions using the same headers. The response contains the transaction history under data[].

The same pattern (list endpoint → pick id → fetch sub-resource) applies to every other data family — credit cards, loans, investments, and so on. Just request the matching permissions in step 2 and call the appropriate endpoints from the Data Consumption reference.

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.

Headers
content-typerequired application/json
Body
{
  "client_id": "<your-client-id>",
  "client_secret": "<your-client-secret>"
}
Response (200)
{
  "access_token": "eyJhbGciOi...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "eyJhbGciOi..."
}

Send the access_token as Authorization: Bearer <access_token> on every subsequent call. Persist the refresh_token securely — it's how you'll renew access without re-submitting credentials.

POST/auth/v1/refresh

Exchanges a refresh token for a new access token (and a new refresh token).

Headers
content-typerequired application/json
Body
{
  "refresh_token": "<your-refresh-token>"
}
Response (200)
{
  "access_token": "eyJhbGciOi...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "eyJhbGciOi..."
}

The previous refresh token is rotated on every successful refresh — discard it and persist the new one.

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".

Headers
Authorizationrequired Bearer <access_token>
Response (200)
[
  {
    "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." }]
  }
]

Each entry can carry multiple AuthorisationServerIds; treat each one as a separate selectable institution since they may correspond to different brands or product lines under the same legal entity.

Data Consumption (Phase 2) — Authenticated GETs

All endpoints in this section follow the same shape:

Customers

EndpointNotes
GET /open-finance/customers/v2/personal/identificationsNatural person identification
GET /open-finance/customers/v2/business/identificationsLegal entity identification
GET /open-finance/customers/v2/personal/financial-relationsPersonal financial relationships
GET /open-finance/customers/v2/business/financial-relationsBusiness financial relationships
GET /open-finance/customers/v2/personal/qualificationsPersonal qualifications (income, etc.)
GET /open-finance/customers/v2/business/qualificationsBusiness qualifications

Accounts (Checking / Savings)

EndpointNotes
GET /open-finance/accounts/v2/accountsList accounts
GET /open-finance/accounts/v2/accounts/{accountId}Account details
GET /open-finance/accounts/v2/accounts/{accountId}/balancesBalances
GET /open-finance/accounts/v2/accounts/{accountId}/overdraft-limitsOverdraft limits
GET /open-finance/accounts/v2/accounts/{accountId}/transactionsTransactions

Credit Cards

EndpointNotes
GET /open-finance/credit-cards-accounts/v2/accountsList card accounts
GET /open-finance/credit-cards-accounts/v2/accounts/{id}Card account details
GET /open-finance/credit-cards-accounts/v2/accounts/{id}/billsBills
GET /open-finance/credit-cards-accounts/v2/accounts/{id}/bills/{billId}/transactionsBill transactions
GET /open-finance/credit-cards-accounts/v2/accounts/{id}/limitsCard limits
GET /open-finance/credit-cards-accounts/v2/accounts/{id}/transactionsCard 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/contractsList contracts
GET /open-finance/{scope}/v2/contracts/{contractId}Contract details
GET /open-finance/{scope}/v2/contracts/{contractId}/paymentsPayment history
GET /open-finance/{scope}/v2/contracts/{contractId}/scheduled-instalmentsScheduled instalments
GET /open-finance/{scope}/v2/contracts/{contractId}/warrantiesCollateral / warranties

Investments (5 families)

Scopes: bank-fixed-incomes, credit-fixed-incomes, variable-incomes, treasure-titles, funds.

EndpointNotes
GET /open-finance/{scope}/v1/investmentsList investments
GET /open-finance/{scope}/v1/investments/{id}Investment details
GET /open-finance/{scope}/v1/investments/{id}/balancesBalances
GET /open-finance/{scope}/v1/investments/{id}/transactionsHistorical transactions
GET /open-finance/{scope}/v1/investments/{id}/transactions-currentCurrent-period transactions

Exchanges (FX)

EndpointNotes
GET /open-finance/exchanges/v1/operationsList FX operations
GET /open-finance/exchanges/v1/operations/{operationId}Operation details
GET /open-finance/exchanges/v1/operations/{operationId}/eventsOperation events

Resources (discovery)

EndpointNotes
GET /open-finance/resources/v3/resourcesLists 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.

Headers
Authorizationrequired Bearer <access_token>
content-typerequired application/json
Body
{
  "document": "12345678901",
  "representativeCpf": "98765432100"
}
Body fields
FieldTypeNotes
documentstringrequired The end user's CPF (11 digits) or CNPJ (14 digits)
representativeCpfstringoptional The representative's CPF — only used when document is a CNPJ and a legal-entity representative is acting on behalf of the company
Response (200)
{
  "redirectUrl": "https://.../management/?token=..."
}

The URL is single-use and short-lived. Redirect the user immediately; don't persist it.

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.

CategoryPermissions to request
customers (natural person)CUSTOMERS_PERSONAL_IDENTIFICATIONS_READ, CUSTOMERS_PERSONAL_ADITTIONALINFO_READ
customers (legal entity)CUSTOMERS_BUSINESS_IDENTIFICATIONS_READ, CUSTOMERS_BUSINESS_ADITTIONALINFO_READ
accountsACCOUNTS_READ, ACCOUNTS_BALANCES_READ, ACCOUNTS_TRANSACTIONS_READ, ACCOUNTS_OVERDRAFT_LIMITS_READ
credit_cardsCREDIT_CARDS_ACCOUNTS_READ, ..._BILLS_READ, ..._BILLS_TRANSACTIONS_READ, ..._LIMITS_READ, ..._TRANSACTIONS_READ
invoice_financingsINVOICE_FINANCINGS_READ, ..._PAYMENTS_READ, ..._SCHEDULED_INSTALMENTS_READ, ..._WARRANTIES_READ
financingsFINANCINGS_READ, ..._PAYMENTS_READ, ..._SCHEDULED_INSTALMENTS_READ, ..._WARRANTIES_READ
loansLOANS_READ, ..._PAYMENTS_READ, ..._SCHEDULED_INSTALMENTS_READ, ..._WARRANTIES_READ
unarranged_overdraftUNARRANGED_ACCOUNTS_OVERDRAFT_READ, ..._PAYMENTS_READ, ..._SCHEDULED_INSTALMENTS_READ, ..._WARRANTIES_READ
bank_fixed_incomesBANK_FIXED_INCOMES_READ
credit_fixed_incomesCREDIT_FIXED_INCOMES_READ
variable_incomesVARIABLE_INCOMES_READ
treasure_titlesTREASURE_TITLES_READ
fundsFUNDS_READ
exchangesEXCHANGES_READ
(always)RESOURCES_READ

Cumbuca Open Finance — Data Sharing API Reference.