On a self-hosted deployment, your team operates the service. On Lerian Cloud, Lerian runs the service and sets up the JD connection, the public QR domain, the CRM connection, and every service that the rail talks to. In both cases, the rest of the setup is yours to run: your books in Midaz, your holder records in the CRM, your accounting routes, and the rail settings.
The tenant and its direct participants
A tenant holds one or more direct participants. By default, it holds the single institution that its binding names. With the organization catalog, it can hold the several regulated institutions of one economic group. Each of them is a direct participant in its own right, with its own books. See Multi-organization and ledgers. Every call is authenticated with the tenant’s own machine-to-machine credentials, and the tenant comes from the validated bearer — never from a payload or a path. The institutions you host as indirect participants live inside your tenant and never hold a credential of their own. An indirect’s id on a request serves as routing data. It decides which settlement position the money moves on. The guarantee that the request really belongs to that institution is yours to make before you send it. The one anonymous exception is the public QR payload and JWKS routes, whose caller is the payer’s PSP — a party that was never registered with you. The direct and indirect model explains the two participation types. It also shows who holds the settlement account at the Banco Central, and where each hosted institution’s money lives.
The domain map
Each domain below is a section of the API reference. This page gives one sentence per domain. The reference has the full contract: when to call each operation, which side calls it, and what it refuses. Each link opens a typical operation of its section.
- Key entries: register, change, and remove the Pix keys of your accounts in the DICT. It also has batch verification and the two bulk-removal flows, for account closure and for holder removal.
- Key claims: the BACEN process to take a key from another PSP. It covers portability of your own key and ownership claims, with both sides of the negotiation.
- Banks: the national SPI participant catalog, read live from JDPI.
- Transactions: outbound payments over SPI (two-phase, asynchronous), or settled on your own book when the payee is on-us. It also has the read surface that closes the loop.
- Refunds: the devolução of a payment that you received, started by the payee. Each one is a new transaction row, capped at the original amount.
- Limits: per-account outbound transaction limits. The account’s first outbound payment creates them, and the rail applies them before any money moves.
- QR codes: static and immediate dynamic codes with self-hosted signed payloads, decode, and listing. The section’s introduction documents the anonymous public payload and JWKS routes.
- Webhooks: the inbound routes that JDPI calls on you. They cover cash-in, the devolução started by the payee’s bank, and account validation, synchronous and asynchronous.
- Indirect participants: the registry of the institutions that reach SPI through your ISPB. It covers their lifecycle, settlement positions, delivery notices, and the reconciliation feed.
- MED 2.0: BACEN’s special return mechanism. It covers infraction reports, refund requests in both roles, creator-side value recoveries, and fraud markers. The credit of a refund that you won arrives on the devolução webhook, with return code BE08 or FR01.
- Pix Automático: recurring authorizations, their schedules, and composite QR codes. It also has the inbound registration, settlement, and event routes that JDPI calls on you.
- Systemplane: the runtime-configuration surface for operators. Payment clients never need it. The platform documentation covers its routes, and this reference does not.
Payment orders and devoluções
These rules apply to every client that sends money through the rail:
- Send the
X-Idempotencyheader on every payment order (POST /v1/transactions) and every devolução (POST /v1/refunds). Use a stable business string of 255 bytes or less. Without it, the rail answers400 PIX-0061before any ledger or JDPI call. - A resend under a recorded key moves no money. It answers
409 PIX-0029. A payment order with theendToEndIdof a recorded order gets the same answer. Read the outcome of the first request with aGET. - A resend under the key of a refused order answers
409 PIX-0133. JD refused or never received that order, so no money moved. To pay, send a new order under a new key. - The key belongs to the payer. The payer is the organization that pays, plus the indirect participant on an indirect order or devolução. Two payers can use the same key value.
- A payment order does not carry the payer’s Pix key. A body with a top-level
keyfield answers400 PIX-0061. The payee’s key,payee.key, does not change. - A devolução of a Pix that an indirect participant received carries its
indirectId. Otherwise the rail answers422 PIX-0135. See Indirect participants. - A Pix Automático debit posts on the account that the authorization names. When the authorization names no account, the debit uses the payer’s only account. A payer with two or more accounts and no account on the authorization gets
400 PIX-0061, before any posting.
Pix by key to a third party
To pay a Pix key held at any institution, look the key up first and pay with what the lookup returns:
- Look up the receiver’s key with Look up a Pix key before paying it (
GET /v1/entries/{entryId}/lookup).entryIdis the key value, URL-encoded.account_idis the payer’s account, the one the payment leaves from. The DICT lookup is made on behalf of the payer: DICT counts it against the payer’s CPF or CNPJ. When this deployment acts as several direct participants,ispbnames the one that pays. - Read the answer. It returns an
endToEndIdand apayeeblock with exactly the fields thatPOST /v1/transactionsexpects. The account number comes whole inpayee.accountNumber, as the DICT returns it, andpayee.accountDigitis empty. - Pay with
POST /v1/transactions, sending thatendToEndIdand thatpayeeas they are. The payment goes to JD as a payment initiated by key. Without theendToEndId, it goes out as a manually typed order.
POST /v1/entries/verification.
The lookup answers these errors:
The lookup limit. By default, a payer account can make 100 lookups per 60 seconds. The limit applies always, apart from the general request limits. The operator tunes it in the systemplane namespace
plugin-br-pix-jd.http, with the keys rate_limit.key_lookup.max and rate_limit.key_lookup.window_sec.
A payment by key to a payee at your own institution is checked against the DICT. Before the payment settles on your book, the rail compares the payee’s ISPB, branch, account, account type, and document with the account that the DICT binds the key to. A field that differs answers 422 PIX-0033, naming the field, and no money moves. Send the payee that the lookup returned and the check passes.
Money: one API, two units
This API’s own contract gives every money field as an int64 count of centavos. For example,
110001 means R$ 1.100,01. That rule covers JSON bodies, query, path, and header.
JDPI authors some bodies: the webhook routes and the Pix Automático inbound, settlement, and event routes. On those bodies, every money field is a JSON number in reais (1100.01). That is JD’s contract on the payloads that JD sends. The rail converts to centavos at the boundary.
The side that authored the body sets the unit, never the field’s language. Portuguese-named fields on this API’s own write surfaces still carry integer centavos. Each field’s description in the reference gives its unit.
Field names: English, with the Portuguese names deprecated
MED 2.0, Pix Automático, and the key lookup name their fields in English:
recoveryId for idRecValores, recurrenceId for idRecorrencia, taxId for cpfCnpj, and so on. The Portuguese names still work, and they are deprecated. Each field’s description in the reference names its replacement.
- Responses carry both names, with the same value. Read the English name.
- Requests accept either name, in the body and in the query. If you send both, they must carry the same value. Two different values are refused with
400 PIX-0148. - Two MED routes have English paths:
GET /v1/med/recoveries/awaiting-returnandPOST /v1/med/recoveries/{idRecValores}/return. They answer exactly likeawaiting-devolveranddevolver, which still work and are deprecated, and they need the same permission.
Errors
Errors are RFC 9457
application/problem+json. Every error carries a PIX-XXXX taxonomy code in the code member. Match on the code, never on the human-readable text.
The Pix JD error list has every code, with the exact detail of each one.
How Pix movements land in Midaz
The direct participation plugin posts every settled Pix movement to Midaz as a ledger transaction. The external leg goes against the clearing account (for example,
@external/BRL). Settled movements include cash-out, cash-in, refunds (devolução), MED effectuation legs, and Pix Automático settlement. Midaz records the accounting entry. The payer and payee identity (bank, branch, account, holder name and document, Pix key) lives only in the plugin’s own transaction record. Every BACEN reference lives only in that record.
Correlation between the two systems works through identifiers, not metadata:
- The end-to-end ID (E2E) is the idempotency key of the Midaz posting, so a retried settlement can never double-post to the ledger. Follow-up legs of the same E2E (a devolução or a MED effectuation) derive their key from the E2E with a flow suffix. They never collide with the original posting.
- The plugin stores the Midaz posting ID on its own transaction record. It uses that ID to commit or cancel the pending debit of a two-phase cash-out.
Where to start
- Setting up the rail: the setup trail, in the order you act, for a service that is already running. It covers the prerequisites, payment-order signing, the Midaz ledger and CRM records, the accounting routes, the plugin settings, and the checks that prove each step. Follow it from top to bottom.
- Payment-order signing: step 2 of the trail, only if JD requires signed payment orders for your institution.
- Environment variables: the deployment variables of the service, with their format and default.
- The direct and indirect model: the two participation types, and where an indirect participant’s money lives. Then read Hosting indirect participants, with the extra steps for a deployment that settles Pix for other institutions. Skip both if you settle only the Pix of your own customers.
- The API reference: pick your domain in the map above. Each link opens a typical operation of its section.
Lerian provisions the provider-specific configuration for direct participation via JD with your integration. To set up direct Pix participation, get in touch with our team.

