> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lerian.studio/llms.txt
> Use this file to discover all available pages before exploring further.

# Create a PIX transaction

> Creates an outbound PIX payment. What happens next depends on where the payee is, and the two branches answer with different statuses and different bodies — a client has to handle both.

An on-us payee (payee.ispb equal to this participant's own ISPB, on a direct order) settles SYNCHRONOUSLY as an INTRA_PSP ledger transfer and answers 201 with the transaction already EXECUTED. The account credited is the one payee.branch, payee.accountNumber and payee.accountDigit name, and it must belong to payee.document (422 PIX-0134). On a payment by key (payee.key) those coordinates are first checked against DICT (§8.2.14, asked as the payer; JDPI answers a key of this institution from its own base): a field the order states differently from the account DICT binds the key to is refused 422 PIX-0033 naming that field (the branch is compared by value, so "1" and "0001" name the same branch, here and in the paying participant's records), a key DICT does not hold is 404 PIX-1011, and JDPI unavailable is 503 PIX-1050 — all before anything is held. Send the payee object GET /v1/entries/{entryId}/lookup answered and it matches. Any other payee settles over SPI in TWO PHASES: the amount is first HELD on the paying position as a pending ledger debit, and only then is the order submitted to JDPI (§8.4.1), which is asynchronous by design — nothing has settled when the call returns. A direct order answers 201 with the transaction PENDING; an order routed through a registered indirect (indirectId in the body) answers 202 carrying JD's own §8.4.1 acknowledgement byte-for-byte when JDPI returns one, whose idReqJdPi is the handle the outcome is read with, and 201 PENDING with this plugin's body when JDPI's answer proves nothing. Either way, poll GET /v1/transactions/{transactionId}: a background reconciler consults JDPI §8.4.2 and then commits or cancels the hold, and the money is not settled until the status says so.

WHAT indirectId ACTUALLY MOVES, because it is more than a label. This participant may serve INDIRECT participants — other institutions registered here with POST /v1/indirects that reach SPI through this participant's ISPB. Naming one on an order changes THREE things at once: the amount is held on that institution's `@pi_{ispb}` settlement position instead of on the payer's own, the persisted order is stamped with that institution so it appears in GET /v1/indirects/{indirectId}/transactions, and the response shape changes from 201-plus-plugin-body to 202-plus-JD-body whenever JDPI acknowledges the order. The identifier is ROUTING DATA, not a credential: this participant authenticates you, and guaranteeing that the order really belongs to that institution is your responsibility, not this API's.

WHO PAYS AN INDIRECT ORDER. An indirect keeps its customers in its own core, never in this participant's books, so the ledger counterparty of its order is always its `@pi_{ispb}` position. The indirect DECLARES the customer who pays in payer (document, name, branch, accountNumber, accountDigit, accountType): this plugin reads no record of it and sends that block to JD as the payer of the order, on the indirect's ISPB, exactly as sent. payer is refused 400 PIX-0061 on a direct order, together with accountId, or with a document that is not a CPF or CNPJ; an indirect order with neither is 400 PIX-0061 naming payer; a declared accountType 4 (Conta PI) is 422 PIX-0098. Naming the payer by accountId on an indirect order is DEPRECATED: it names a customer of THIS participant, and it is accepted, unchanged, only when this participant's own credential sends the order — when an Access Manager partner is behind the request it is refused 400 PIX-0061 naming accountId, so a partner confined to one indirect cannot present another customer as the payer nor spend that customer's limits. An order with a declared payer runs no account limit check: its customer's limits are the indirect's, kept in its own core, and the `@pi_{ispb}` balance the hold checks bounds it.

⚠️ indirectId IS REFUSED 422 PIX-0111 WHILE THIS TENANT'S INDIRECT-PARTICIPANTS FEATURE IS SWITCHED OFF, and the refusal names the setting an operator has to turn on. The order is never quietly executed as a DIRECT one: that would hold the amount on the payer's own position instead of the institution's `@pi_{ispb}`, so the money would leave an account you never named, behind a 201. The refusal is decided before the payer is read, so nothing is held and no order is persisted. An order carrying NO indirectId is unaffected.

When the order reaches its outcome, an indirect order may ALSO push a NOTICE to the endpoint that registration carries (delivery.endpointUrl), queued by the background reconciler once JD's terminal outcome is known — an HTTPS POST forwarding JD's own result body verbatim, carrying X-Lerian-Signature ('sha256=' followed by the hex HMAC-SHA256 of the exact body bytes under the registration's shared secret) and X-Lerian-Timestamp. **Do not build on the notice arriving.** No notice is queued at all when this deployment has no outbound queue configured, and none is queued when the outcome carries no JD result body to forward — an order cancelled locally, without a JD answer, is exactly that case. Delivery of a notice that WAS queued is AT-LEAST-ONCE and can still fail permanently while the payment stands. So the institution must dedup on the end-to-end id and treat GET /v1/indirects/{indirectId}/transactions, not the notice, as the record of truth: it is the only place an outcome whose notice was never queued becomes visible. A direct order pushes no notice at all.

End-to-end ids: send endToEndId only when you already hold one (from a key lookup or a QR decode), and then payee.key is mandatory with it. Omit it on a manually typed order: SPI mints one, or this plugin does when it signs the paying participant's orders — the response carries the value either way. A QR decode is NOT a key lookup: to pay a decoded QR, send the qrCodeType POST /v1/qrcodes/decode answered, together with its endToEndId and payee.key, or the order goes out as a payment by key and the payee cannot conciliate it (JDPI §8.4.1: tpIniciacao 2 for STATIC, 3 for DYNAMIC). qrCodeType is what makes it a QR payment; txId (sent as idConciliacaoRecebedor, verbatim, never trimmed) follows its type: optional on STATIC, required on DYNAMIC. An invalid combination is refused 400 PIX-0061 naming the field, before anything is held: txId without qrCodeType, qrCodeType without payee.key or endToEndId, a STATIC txId that is neither *** nor up to 25 alphanumeric characters (JDPI §8.4.1; a static QR may decode to one, e.g. TX-001, since §8.3.1/§8.3.3 state no charset, and such a txId cannot be sent), a DYNAMIC txId missing or not 26 to 35 alphanumeric characters. The two fields reach SPI orders only: an on-us payee and a transfer to another core of the same ISPB ignore them. Idempotency: the X-Idempotency header is REQUIRED, and it is what makes a retry safe on every branch, on-us included: once an order is recorded under a key, a resend under that key is refused 409 PIX-0029 and moves no money. Keys are scoped to the payer (the organization, plus the indirect participant on an indirect order); a new order needs a new key. Amounts are integer centavos.

Every refusal below is decided before the hold is taken, so it moves ZERO money, except the cross-core answers PIX-0145, PIX-0146 and PIX-0149, which come after the hold and release it; when JDPI refuses the order after the hold exists, the call answers the refusal, the hold is released and the order stays in GET /v1/transactions with status ERROR — or PENDING, when the ledger does not confirm the release, until the background reconciler resolves it; when JDPI's answer does not prove a refusal (a timeout, a 5xx, a 408, 409 or 422 — except JD's payment-signature refusals JDPISPI017 and JDPISPI018, which prove one whatever status carries them and are never re-sent), the hold is kept and the order answers 201 PENDING with this plugin's body, an indirect order included, its final status coming later. The same release follows 409 PIX-0136, refused before JDPI is called when the paying participant's payment-order signing settings are written but cannot sign (a setting missing, an algorithm this plugin does not sign with, a key that does not fit it, or a certificate that is not the key's own); the message names the setting, and nothing reaches JDPI unsigned. Refusals: 409 PIX-0029 when this endToEndId or X-Idempotency key was already used by an order that may have moved money, and 409 PIX-0133 when that order was refused and moved none (send a new order under a new key); 409 PIX-0076 when the paying position lacks the amount; 422 PIX-4009 when the ledger itself refuses the hold or the on-us posting for lack of funds (a race past PIX-0076, or an overdraft limit it would exceed), 422 PIX-4007 when it refuses a same-ledger on-us payment because an account on it has no balance it can post to (none opened in that ledger, or a deleted one), 400 PIX-4005 when it refuses one because an account on it may not send or receive or is blocked, and 422 PIX-4018 when the client's own transaction rules deny the posting — the ledger refused, so nothing moved and the order stays ERROR;409 PIX-0078 on a transfer to the same account; 409 PIX-0075 when the account's period limit is exceeded; 422 PIX-0030 on a non-positive amount; 422 PIX-0162 when feeContext names a label no fee package of the payer's ledger selects on, enabled or not, or that ledger does not price Pix by fee package; 422 PIX-0037 when endToEndId arrives without payee.key; 422 PIX-0108 when the payer — or, on an indirect order, the indirect's `@pi` — resolves in the CRM but is not bound to a ledger account; 422 PIX-0111 when an indirectId is supplied while this deployment's indirect-participants feature is off (naming the setting to enable — the order is refused, never quietly paid from the payer's own account), 404 PIX-0095 for an unknown or malformed indirectId and 422 PIX-0100 when the indirect it names is not ACTIVE; 422 PIX-0127 when this deployment acts as SEVERAL direct participants and the order names none of them in payerIspb, and 422 PIX-0128 when the one it names is not among them; when the payee banks at the PAYING participant — the order would normally settle internally, never touching SPI — and that participant has declared its ISPB shared with another core, the ownership map says which books hold the account the order names (payee.branch, payee.accountNumber and payee.accountDigit; a payment account, accountType 3, by its account alone), asked before the payee is looked up. When the OTHER core holds it, the order is a cross-core transfer, never sent over SPI: the amount is held on the payer's account and the order is relayed to that core, answering 201 EXECUTED once it credited the payee, 201 PENDING while its answer is unknown (the hold stays and the background worker resends and settles it; poll GET /v1/transactions), 422 PIX-0145 when it refused the credit and 503 PIX-0146 when the order never reached it — both release the hold, so nothing was debited, and the order stays in GET /v1/transactions with status ERROR (send it again under a new X-Idempotency key); and 409 PIX-0149 when any fee in the package priced on the cross-core route (this leg to the other core of the same participant, priced like a Pix sent to another bank) is configured to deduct from the amount instead of being charged on top (an operator setting) — the applied package is known only once the hold is posted, so this refusal comes after the hold and before anything is relayed: the hold is released and the order stays ERROR, or PENDING until the background worker finishes a release the ledger did not confirm; nothing was debited; and 409 PIX-0150 when the paying ledger holds no @intercore account, the clearing account a cross-core transfer moves through (an operator setting): the ledger refuses the hold, nothing was debited, the order stays ERROR and the message names the organization and ledger to create it in. Otherwise: 422 PIX-0129 when the map holds that account nowhere, 422 PIX-0132 when the order's account cannot be used to ask (a blank account, a blank branch on anything but a payment account, or one the map refuses as malformed — a retry changes nothing), 503 PIX-0130 when it could not answer (safe to retry: nothing was created) and 502 PIX-0131 when it answered in a form that cannot be acted on; each of these four is refused before anything is held and is NOT rerouted over SPI; an on-us payment WITHOUT payee.key is a payment by bank details, and it is credited on the account payee.branch, payee.accountNumber and payee.accountDigit name — number and digit together, exactly the account an interbank Pix carries — which must belong to payee.document, as the receiving institution checks on an interbank Pix: 404 PIX-2016 when the paying participant holds no such account, 422 PIX-0134 when it belongs to someone else, 422 PIX-0033 when no account is typed, 422 PIX-0108 when it is not bound to a ledger account (a payment account, accountType 3, is looked up by its account alone); an on-us payment WITH payee.key is credited on the account payee.branch, payee.accountNumber and payee.accountDigit name once DICT has confirmed them, checked exactly as a payment by bank details (404 PIX-2016, 422 PIX-0134), while an order naming no account is 422 PIX-0033; 422 PIX-0108 when that payee is not bound to a ledger account; 422 PIX-0102 when payerIspb is supplied on an indirect order and is not the participant recorded at that indirect's registration; 409 PIX-0105 when the ledger the money leaves from declares no accounting route for the direction; when the payer or the on-us payee cannot be used as the order addresses it, nothing is reserved and the answer names what refused: 422 PIX-0137 when the account is held in a ledger that is not configured for Pix on the paying participant (pay from or to an account on a configured ledger, or have the operator add that ledger to the Pix setup), 422 PIX-0138 when the account's record does not say which ledger holds it, 422 PIX-0139 when the payer's record names a different institution than the one paying, 422 PIX-0141 when, on an indirect order, the payer account is not in the ledger the indirect is mounted on, and 409 PIX-0140 when the indirect is mounted on books no longer configured for Pix (an operator setting); a refusal of the payer names the payer account (accountId) in its message, while a refusal of the on-us payee — PIX-0137 or PIX-0138 — names no account, because on a payment by key the payee's account is one you never saw, so read it as the payee the order addressed; 400 PIX-0061 when the X-Idempotency header is missing, blank or over 255 bytes, when a direct order has no accountId, when payer is sent where it does not belong or with a document that is not a CPF or CNPJ, when an indirect order has neither payer nor accountId, when a partner names accountId on an indirect order, when an accountType is outside the PIX domain 0..4, or when feeContext is malformed or sent with indirectId. Called with a partner credential, the order is also decided by that partner's own rules for the ledger and the CRM this plugin calls to serve it: 403 PIX-4019 when Midaz refuses the partner and 403 PIX-2025 when the CRM does, the message naming the reason (other_tenant, suspended, no_longer_valid or not_allowed) — grant the partner the missing permission on that service; a partner holding no grant for those services is decided by its Pix grant alone. On an indirect order a JD refusal is passed back with JD's own status and body instead of a problem+json. An on-us payee who banks at the paying participant but in a DIFFERENT ledger of it is served rather than refused: the amount is reserved on the payer's ledger, credited on the payee's ledger, and the reserve is then committed — so the order answers EXECUTED only once both legs landed. Both on-us shapes persist their transaction before the first posting, so their failures are not invisible: an order the ledger refuses answers an error AND leaves a transaction you will find in GET /v1/transactions with status ERROR (it does not count against the account's period limit: only a hold that reached the ledger does); a same-ledger order whose posting the ledger leaves unknown answers 5xx and stays PENDING until the reconcile worker finds the posting and settles it EXECUTED — a posting the ledger does not show yet never fails the order, because the ledger may record a posting after answering for it; and a cross-ledger order whose credit the payee's ledger has not yet confirmed delivered is ACCEPTED and still settling: it answers 201 with status PENDING, the money stays held, and the reconcile worker completes it — poll GET /v1/transactions rather than retrying it as a fresh payment. NOT every failure on that branch became a 201, and the exception matters because the money has already moved: when the credit HAS landed and the ledger then leaves the outcome of CLOSING the hold unknown — the settle failed, or a release could not be proved — the order still answers 5xx AND still leaves the transaction PENDING. So a 5xx here never means nothing happened. Poll GET /v1/transactions; if you retry, retry with the SAME X-Idempotency key, because a fresh key is a second payment.



## OpenAPI

````yaml /pt/openapi/v3-current/pix.yaml post /v1/transactions
openapi: 3.1.0
info:
  contact:
    email: contact@lerian.studio
    name: Lerian Studio
    url: https://lerian.studio
  description: >-
    The API of a DIRECT Brazilian PIX participant, integrated with BACEN's DICT
    (key directory) and SPI (settlement) rails through JDPI. It covers the
    directory (key entries and claims), payments and devolutions over SPI or
    on-us, per-account limits, QR codes with self-hosted signed payloads, the
    inbound webhooks JDPI calls on this participant, MED 2.0 (BACEN's special
    return mechanism), PIX Automático (recurring payments), and the registry of
    INDIRECT participants served through this participant's ISPB.


    ## Domain map


    - **Entries** / **Claims** — the DICT directory: registering PIX keys, and
    the claim process for taking a key over from another PSP.

    - **Transactions** / **Refunds** / **Limits** / **Banks** — SPI payments:
    outbound orders (two-phase over SPI, synchronous on-us), payee-initiated
    devolutions, per-account outbound limits, and the live SPI participant
    catalog. ⚠️ **BREAKING**: the payer's PIX key is gone from payment orders,
    so a `POST /v1/transactions` body still carrying the top-level `key` is
    refused `400 PIX-0061` (the payee's `payee.key` is unchanged).

    - **QR Codes** — static and immediate dynamic QR codes, decode, and the
    anonymous public routes serving signed payloads to payer PSPs (documented in
    the tag).

    - **Webhooks** — the inbound mirror: cash-in, payee-bank-initiated refund,
    and synchronous account validation, called BY JDPI on this participant.

    - **Indirects** — the institutions this direct participant serves: registry,
    lifecycle, settlement positions, delivery notices, reconciliation feed, and
    the optional own QR certificate.

    - **MED Infractions / Refunds / Recoveries / Fraud Markers** — MED 2.0:
    infraction reports, the refund-request money flow in both roles,
    creator-side value recoveries and DICT fraud markers. A MED settlement
    credit arrives on the §9.3.3 refund webhook under Webhooks.

    - **PIX Automatico** — recurring authorizations, schedules, composite QR
    codes, the inbound registration/validation and settlement legs JDPI calls,
    and the event-stream ingress.

    ## Authentication


    Every operation requires a bearer token minted by the platform's
    machine-to-machine (M2M) OAuth flow with the DIRECT participant's
    credentials; authorization is per resource with actions mirroring the HTTP
    verbs. INDIRECT participants never hold a credential: an indirect's id on a
    request is ROUTING DATA supplied and guaranteed by the direct participant,
    not an authentication principal. The exception to authentication is the
    public QR payload/JWKS routes described under the QR Codes tag, which are
    anonymous by construction — the payer's PSP, not a registered client, is
    their caller.


    ## Money: one API, two units


    Every money field of THIS API's contract is an **int64 count of centavos** —
    in JSON bodies, query, path and header alike (`110001` means R$ 1.100,01).
    Every money field on a body AUTHORED BY JDPI — the inbound webhook mirrors
    under Webhooks and the PIX Automático inbound/settlement/event routes — is a
    **JSON number in reais** (`1100.01`), because that is JD's contract on the
    payloads JD sends, converted to centavos at the boundary. The discriminator
    is WHICH SIDE AUTHORED THE BODY: every money field on this API's own write
    surfaces, MED writes included, is integer centavos. Each field's description
    states its unit.


    ## Accounts


    A request names one of this participant's accounts — an `accountId` field or
    an `account_id` parameter — by its **Midaz ledger account id**: the
    `accountId` its CRM alias records, never the CRM alias's own `id`. It is
    looked up in the books of the participant the request addresses, and an id
    not found there is refused `404 PIX-2016` (`404 PIX-0063` on entry details).
    Two exceptions carry the account's ledger **alias** (`@...`) instead: every
    `accountId` in a response, and the `account_id` filter of the transaction
    list, which matches the alias a row carries and answers an empty list when
    none does.


    ## Errors


    Errors are RFC 9457 `application/problem+json`, and every one carries a
    `PIX-XXXX` taxonomy code in the `code` member — match on the code, not on
    the human-readable text. The status discipline is ATTRIBUTION: a 4xx means
    the request, or the data the request names, is what failed (the body names
    the field or entity); a 5xx names the failing dependency (e.g. `503
    PIX-1050` — the JDPI service is temporarily unavailable) rather than hiding
    behind a generic error; a ledger outage (`PIX-4002`) also carries
    `Retry-After`, in seconds. `500 PIX-0109` is the one deliberate exception:
    an unattributed internal failure, whose detail is scrubbed — as is every
    response body with status 500 or above.


    ## Idempotency


    Three families, each protecting a different leg:


    - **The `X-Idempotency` header** is REQUIRED on payment orders (`POST
    /v1/transactions`), on refunds (`POST /v1/refunds`) and on the ten MED write
    operations, and it is the SAME header, by the same name, that the Midaz
    ledger takes on its transaction routes — one integration, one header. Send
    any stable business string; omitting it is refused `400 PIX-0061` before any
    ledger or JDPI call. On a payment order it is the only identifier that
    exists BEFORE the JDPI call, so it protects every branch, on-us included: a
    resend of an order already recorded under the key — or under its
    `endToEndId` — is refused `409 PIX-0029` and moves no money, and so is a
    resend of a refund already recorded under its key. Payment and refund keys
    are scoped to the payer: the organization, plus the indirect participant on
    an indirect order or refund. ⚠️ **BREAKING**: payment orders and refunds
    took the value as the optional body field `clientRequestId` and MED writes
    as the body field `idempotencyKey`; both fields are gone, and three MED
    writes (cancel a refund request, cancel an infraction, return a recovery)
    now take no request body at all.

    - **The JDPI `Chave-Idempotencia`**: the value you send on `X-Idempotency`
    is a SEED — it is projected to a deterministic GUID (UUIDv5) before being
    forwarded, so one client key always lands in one JDPI dedup slot and a retry
    stays a retry inside JD's 24h window. Correlate JDPI-side logs with the
    projection, never with the raw value. DICT writes derive their key from the
    full request, so a transport retry never double-applies.

    - **Ledger postings** are idempotent per order, namespaced per LEG, so the
    two legs of one devolution (or a debit and its reversal) can never collide
    on one idempotency slot.


    Multi-tenant deployments resolve the tenant from the validated token, never
    from payloads or paths; the public QR routes' ISPB path segment is a routing
    selector for public key material, not an identity.
  license:
    name: Lerian Studio General License
  title: Pix JD API
  version: 1.0.0
servers: []
security:
  - BearerAuth: []
tags:
  - description: >-
      The SPI participant catalog (JDPI §8.6.1), read live from JDPI on every
      call with nothing cached — latency and availability here are JDPI's, and
      an unreachable JDPI answers 503 PIX-1050. Two projections of the same
      catalog: GET /v1/banks is the reduced (ispb, legal name) pair a payment
      form needs; GET /v1/banks/participants is the full record with
      participation type, modality and status. Keep ispb a STRING — it is 8
      characters and its leading zeros are significant.


      This is the NATIONAL directory, not this deployment's own registry: a
      participant classified as indirect here (participantType=2) has no
      relation to the indirect participants registered with POST /v1/indirects,
      and neither list implies membership in the other.
    name: Banks
  - description: >-
      DICT key claims: the BACEN process for taking over a PIX key that is
      currently registered at another PSP — portability of your own key, or an
      ownership claim on a key someone else holds. A claim is a negotiation
      between two PSPs mediated by the DICT, and this surface exposes both sides
      of it: open a claim (POST /v1/claims), list and inspect the ones this
      participant is involved in, confirm (the donor side acknowledging),
      conclude (the claimer side completing the transfer), and cancel.


      Claims move no money — they move DIRECTORY state, and several steps are
      irreversible once the DICT records them: a concluded claim has already
      re-pointed the key at the claiming account. Each operation's description
      states which side of the claim calls it and in which claim status it is
      legal; a step attempted out of order is refused with a coded 4xx rather
      than forwarded to the DICT.
    name: Claims
  - description: >-
      DICT key entries: registering, updating, listing and removing the PIX keys
      — CPF/CNPJ, phone, email or random key (EVP) — that bind an addressable
      alias to one of this participant's accounts in the BACEN directory. The
      surface also carries the verification call (a batch existence check
      against the DICT) and the two bulk-removal flows, account closure (POST
      /v1/account-closures) and holder removal (POST /v1/holder-removals), which
      drop every key bound to a coordinate at once.


      The rule integrators trip on: the DICT locates keys by the FULL account
      coordinate — ISPB, branch, account number AND account type (tpConta) — so
      a lookup or removal that names the wrong account type finds nothing,
      silently: the answer is an empty 200, indistinguishable from an account
      that genuinely holds no keys. Registration is idempotent at JDPI through a
      deterministic idempotency projection, so a transport retry of the same
      request does not double-register a key.
    name: Entries
  - description: >-
      **What this domain is.** This participant is a DIRECT PIX participant, and
      it can serve INDIRECT participants: other institutions that reach SPI and
      the DICT through this participant's ISPB. This surface is the registry of
      those institutions — registering one, suspending, reactivating and closing
      it, reading the key set its QR codes are signed with, and reading the
      reconciliation feed of every movement that rode its settlement position.


      **The credential model, because it decides how you integrate.** An
      indirect participant NEVER holds a credential for this API. Every call is
      authenticated as the direct participant, and the indirect's id on an order
      or a registration row is ROUTING DATA: it decides which settlement
      position the money moves on, and the guarantee that a request really
      belongs to that institution is the direct participant's responsibility,
      made before the request is sent — this API does not re-validate it.


      **Where the money moves.** Registering an institution creates a dedicated
      ledger settlement position for it (its `@pi_{ispb}` account), atomically
      with the registry row. From then on: an outbound order carrying its
      indirectId is HELD on that position (the debit source always comes from
      the registry, never from the caller's body), an inbound credit whose
      receiver ISPB matches it is credited to that position, and the response to
      an indirect order is JD's own acknowledgement passed through verbatim
      (202). The feed at GET /v1/indirects/{indirectId}/transactions is the
      record of truth for all of it: windowed (the `since` bound is required),
      cursor-paged, oldest first, amounts in integer centavos.


      **Lifecycle.** ACTIVE ⇄ SUSPENDED → CLOSED. PATCH carries at most ONE
      lifecycle action per request (suspend, reactivate or close) alongside
      ordinary field updates. Suspending flips the settlement position's
      send/receive flags before the registry row changes, so the ledger
      backstops the registry rather than trailing it. CLOSED is terminal and
      requires the settlement position to hold ZERO balance (409 PIX-0096); the
      position is blocked, never deleted, and re-registering the same ISPB later
      reuses it. Repeating the current state is refused 409 PIX-0094 —
      deliberately not a no-op, so a double-fired automation is visible. One
      ISPB maps to at most one non-CLOSED registration (409 PIX-0093).


      **Delivery notices.** When an indirect's registration carries a delivery
      endpoint, the plugin can push JD's own payload BYTE-FOR-BYTE to it as an
      HTTPS POST carrying X-Lerian-Signature ('sha256=' + the hex HMAC-SHA256 of
      the exact body bytes under the registration's shared secret) and
      X-Lerian-Timestamp. Delivery is AT-LEAST-ONCE: the institution MUST dedup
      on the end-to-end id, and must treat the transactions feed — not the
      notice — as the record of truth, because a notice can fail permanently, or
      never be queued at all, while the payment stands. The shared secret is
      write-only: PATCH replaces it, and every read renders it masked.


      **The QR certificate option, which is commercial, not compliance.** By
      default a QR raised for an indirect is signed with the DIRECT
      participant's certificate and hosted on the direct's domain — the ordinary
      arrangement, and no registration step here is needed for an indirect to
      transact. An institution that opts into its OWN certificate registers it
      via PATCH `qrCertificate`: `ownCertificate: true` plus a scheme-less,
      publicly resolvable `publicBaseUrl` (with the shipped path defaults the
      base URL may spend at most 37 of BACEN's 77-character payload-URL budget —
      measure the hostname BEFORE promising it). The whole sub-object is gated
      on this tenant's indirect-participants feature (off = 422 PIX-0111), and
      it should be switched on only after the certificate is live on BACEN's
      list — before that, payments fail silently at the payer's app, which
      validates a signature nothing vouches for. The institution then hosts its
      own signed payloads AND the key set they validate against: read that key
      set with GET /v1/indirects/{indirectId}/jwks (an authenticated operator
      read; 422 PIX-0114 when the institution has no own certificate — the
      direct participant's public JWKS route serves that case) and serve the
      bytes verbatim. A SUSPENDED institution can still read its key set: QRs
      already in the wild still need validating.


      **Refusals to know.** 404 PIX-0095 unknown (or malformed) indirect id — an
      id belonging to another tenant is deliberately indistinguishable from an
      unknown one; 422 PIX-0100 the institution is not ACTIVE; 422 PIX-0102 a
      payer ISPB on an indirect order names anything but the direct participant
      that institution is mounted on (blank, or that participant's own ISPB, are
      the two accepted values — an indirect's own ISPB is never one of them);
      409 PIX-0093/0094/0096 the lifecycle rules above; 422
      PIX-0111/0112/0113/0114 the QR-certificate rules above; 404 PIX-0119 an
      inbound credit for a receiver this participant does not serve.
    name: Indirects
  - description: >-
      Per-account PIX transaction limits, enforced on OUTBOUND money only. Four
      limit rows exist per account — transaction and period, each in a daily and
      a nightly band — and the day/night boundary comes from this institution's
      policy (whole hours, default 06:00–20:00 UTC as the daily window), not
      from the request.


      A fresh account legitimately answers GET /v1/limits with an empty list and
      GET /v1/limits/available with 404: the rows are seeded with defaults by
      the account's FIRST outbound transaction, not at account creation. An
      account with no rows is therefore NOT unlimited — the enforcer seeds and
      then enforces, failing closed if a limit cannot be established. PATCH
      /v1/limits is update-only: it adjusts a row that exists, and naming a
      (type, period) tuple that has no row yet is refused 422 PIX-0036. A
      payment over the applicable limit is refused 409 PIX-0075 before any money
      moves.
    name: Limits
  - description: >-
      MED 2.0 fraud markers: the DICT records this participant creates against a
      person or key involved in fraud, feeding BACEN's shared fraud database.
      Create a marker (POST /v1/med/fraud-markers), cancel one you created, list
      the local working set, inspect one, and query the DICT's own view (GET
      /v1/med/fraud-markers/dict).


      Markers move no money and have a two-party lifecycle: created here,
      acknowledged/consolidated at the DICT. The write operations take the
      client idempotency key on the `X-Idempotency` request header (required; it
      was a body field `idempotencyKey` until this version, and the cancel
      operation now takes no body at all). It is projected to a deterministic
      GUID before reaching JDPI (see the API description's idempotency section),
      so a retry with the same header value lands in the same JDPI dedup slot.
    name: MED Fraud Markers
  - description: >-
      MED 2.0 infraction reports: the notifications that open BACEN's special
      return mechanism on a transaction — typically fraud reported by the
      payer's PSP against a payment this participant received. Inbound reports
      addressed to this participant are collected from JDPI by a background
      poller and land in the local working set automatically; this surface is
      where you SEE them (list, inspect, read JDPI's own view) and ACT on them
      (analyze — agree or disagree — and cancel one this participant created).


      Infractions move no money themselves; they are the predicate for MED
      Refunds, where the money leg lives. Analysis is subject to a BACEN SLA
      measured from the report's creation, and the write operations take the
      client idempotency key on the `X-Idempotency` request header (required; it
      was a body field `idempotencyKey` until this version, and the cancel
      operation now takes no body at all), projected to a deterministic GUID
      before reaching JDPI.
    name: MED Infractions
  - description: >-
      MED 2.0 value recoveries: the creator-side flow this participant runs when
      its own customer was defrauded and the money went to another PSP — open a
      recovery (POST /v1/med/recoveries), amend it while the counterparty
      analysis allows, and, once the counterparty approves, execute the return
      step (POST /v1/med/recoveries/{idRecValores}/return) within the 72-hour
      window that approval arms. GET /v1/med/recoveries/awaiting-return is the
      operator worklist of recoveries whose clock is running.


      The recovery API at JDPI has no pending-list poll, so open recoveries are
      re-synced by a background poller — local state can trail the counterparty
      by one poll interval. The return step is the money-bearing action of the
      flow; everything else is negotiation state. Write operations take the
      client idempotency key on the `X-Idempotency` request header (required; it
      was a body field `idempotencyKey` until this version, and the return
      operation now takes no body at all), projected to a deterministic GUID
      before reaching JDPI.
    name: MED Recoveries
  - description: >-
      MED 2.0 refund requests: the special-return money flow itself. This
      participant appears in BOTH roles — as the REQUESTING PSP it opens a
      refund request against another PSP (POST /v1/med/refunds); as the
      CONTESTED PSP it receives requests (collected from JDPI by a background
      poller — GET /v1/med/refunds/pending-analysis is the analysis worklist),
      analyzes them within the BACEN SLA, and, when it accepts, EFFECTUATES the
      devolution: POST /v1/med/refunds/{idSolDevolucao}/effectuate debits the
      customer who received the original payment and submits the pacs.004 over
      SPI.


      Effectuation is the money leg, and it is two-phase: the debit is HELD as a
      pending ledger posting when the effectuate call is accepted, and a
      background settlement reconciler commits it when SPI settles (or releases
      it on a terminal SPI error) — so an accepted effectuate is not yet settled
      money, and the row's state says which side of that line it is on.
      Direction is guarded on the participant's own ISPB: only the CONTESTED PSP
      (the PSP whose customer RECEIVED the original payment) can effectuate,
      refused 400 PIX-0088 otherwise, and the mirror credit of a refund this
      participant WON arrives on the §9.3.3 refund webhook (POST
      /v1/webhooks/refunds, codes BE08 and FR01) and credits the original payer.
      GET /v1/med/refunds/credits/{endToEndIdDevolucao} reads that credit's
      landing. Every write except effectuate takes the client idempotency key on
      the `X-Idempotency` request header — the same header the Midaz ledger
      takes — required, and projected to a deterministic GUID before reaching
      JDPI, so correlate JDPI-side logs with the projection, not the raw value
      you sent. It was a body field `idempotencyKey` until this version, and the
      cancel operation now takes no body at all.
    name: MED Refunds
  - description: >-
      PIX Automático: BACEN's recurring-payment arrangement, where a payer
      authorizes a merchant's PSP to pull scheduled payments. This surface
      carries the whole arrangement from this participant's seat: recurring
      authorizations (create, confirm, respond, adjust the max value, cancel),
      the payment schedules under them (create, list, cancel), the composite QR
      codes that carry a charge and a recurrence in one artifact (static,
      dynamic, cobv and recurrence-only, with their updates and decode), the
      `/inbound` registration and validation endpoints JDPI calls on this
      participant per annexes §5.2/§5.3, the §5.4 settlement legs (block, debit,
      and the compensating reversal via DELETE), and the §6 event-stream ingress
      (`/events/*`) through which JDPI pushes lifecycle status.


      Which party calls each route matters more here than anywhere else in the
      API: `/inbound/*`, `/events/*` and `/settlements/*` are called BY JDPI on
      this participant, while the rest are called by your systems. Only the JD
      Courier's credential (sourceService jd-courier), JD's existing application
      (sourceService jd-consultores) or an application the tenant lists as JD's
      (tenant_policy/jd.direct_client_ids) may call those; any other caller is
      403 PIX-0005. The §5.4 settlement legs move money — the debit posts
      against the paying customer, the reversal compensates it — and both are
      idempotent per end-to-end id with the reversal namespaced separately, so
      the two legs of one scheduled payment can never collide. Amounts on this
      participant's own operations are integer centavos; the inbound JDPI
      mirrors carry reais as JSON numbers, per the API-wide two-unit rule.
    name: PIX Automatico
  - description: >-
      **What this domain does.** Creates, updates, decodes and lists this
      participant's PIX QR codes: STATIC (a reusable key-and-optional-amount
      code) and IMMEDIATE DYNAMIC (a single-use charge whose payload is a signed
      JWS document fetched by the payer's PSP at pay time). Due-date charges
      (cobv), withdrawal and change (saque/troco) variants are RECOGNIZED by the
      decode operations but not created here; recurring composites live under
      PIX Automatico.


      **Who signs, who hosts — the part that decides your architecture.** JDPI
      holds the certificate and signs every dynamic payload; this plugin
      composes the URLs the QR carries, and by default it also STORES and SERVES
      the signed JWS on its own public routes, so the QR that comes back is
      end-to-end resolvable with no work on your side. The exception is a charge
      raised for an indirect participant that holds its OWN certificate: the
      signed JWS comes back in the create/update response and is NOT stored —
      that response is the ONLY delivery, and the indirect hosts the document
      (and the matching key set, read via GET /v1/indirects/{id}/jwks) on its
      own domain. If that response is lost, the charge nevertheless exists at
      JDPI: recover it via GET /v1/qrcodes/list (match your
      recipientConciliationId) and PUT /v1/qrcodes/dynamic/{documentId}, which
      re-signs and returns a fresh payloadJws rather than reproducing the lost
      one.


      **The dynamic-QR lifecycle.** Create validates everything BEFORE calling
      JDPI — the recipient's name and city come from this participant's CRM
      records, never from the body; the payload URL is composed first because
      JDPI requires it in the request; the conciliation id must be new (409
      PIX-0065) — so a refused create never leaves a charge behind, and a JDPI
      failure after persistence is compensated by deleting the local row. Update
      (JDPI §8.3.5) changes the amount, conciliation, expiration, payer or
      charge status (0=Active, 1=Concluded, 2=Removed by recipient, 3=Removed by
      PSP), and REUSES the location: a printed QR keeps resolving, because the
      updated JWS atomically supersedes the old one at the same path id. The
      plugin stores no charge↔indirect association, so EACH update's indirectId
      decides who signs that revision — omitting it on an indirect-hosted charge
      moves the charge onto the direct participant's certificate and domain.


      **The 77-character budget.** BACEN caps the payload URL (urlPayloadJson)
      at 77 characters, scheme-less, and the path this deployment is configured
      with spends most of it. An over-budget URL is refused by ATTRIBUTION: 422
      PIX-0112 when an indirect's registered base URL is what does not fit
      (choose the hostname against the remaining allowance BEFORE registering
      it), 500 PIX-0053 when the deployment's own configuration leaves no room
      for any charge.


      **Decode and list.** Decode accepts the scanned EMV payload (POST
      /v1/qrcodes/decode) or the payload URL itself (POST
      /v1/qrcodes/decode/url), per §8.3.10. GET /v1/qrcodes/list (§8.3.12)
      requires a bounded registration window of at most 90 days; omitting the
      type fans the query out across every QR type.


      **Public payload & JWKS routes.** Four routes exist OUTSIDE this
      specification — they are anonymous, they are called by the PAYER'S PSP
      (never by you), and they are listed here because they are part of the
      deployment's public contract even though no operation below describes
      them. Their path prefixes (the payload path and the JWK path) and their
      host vary per deployment; the shapes are:


      - `GET /{payloadPath}/cob/{id}` (single-tenant form) and `GET
      /{payloadPath}/{ispb}/cob/{id}` (multi-tenant form, where the ISPB segment
      selects the serving participant) — the signed JWS payload of one dynamic
      charge, returned raw with Content-Type `application/jose`. The `cob`
      segment is LITERAL: only immediate charges are self-hosted, and a `cobv`
      fetch answers 404 rather than handing the payer's PSP a resource of a type
      it did not ask for.

      - `GET /{jwkPath}` (single-tenant) and `GET /{jwkPath}/{ispb}`
      (multi-tenant) — the JWK Set the payloads validate against, as
      `application/jwk-set+json`, served from a short-lived cache (minutes) over
      JDPI's key material.


      The 22-character `{id}` is a cryptographically random token minted per
      charge, and it is the route's only barrier: unguessable by construction,
      it acts as a capability — knowing the URL is what authorizes the fetch,
      which is exactly the EMV model, where the URL travels inside the QR. A
      missing, expired or unknown payload — and an unknown ISPB — answer a
      UNIFORM 404 with code PIX-0063, deliberately not distinguishing absent
      from expired: a payer PSP must not pay an expired QR, and nothing more is
      anyone else's business. Server-side faults (the participant lookup
      unavailable, JDPI unreachable with nothing cached) answer 503. Errors on
      these routes are RFC 9457 problem+json like everywhere else.
    name: QR Codes
  - description: >-
      Refund of a RECEIVED PIX payment — the BACEN rule is that refunds are
      PAYEE-initiated, and this surface encodes it: only the party that received
      the money can return it. A refund never mutates the original transaction;
      it is a NEW transaction row (is_refund=true) whose amount is capped at the
      original minus every prior refund of it (409 PIX-0075 over the cap). GET
      /v1/refunds/reasons is the catalog of accepted devolution reason codes.


      Refunding a payment sent to another institution is refused 400 PIX-0089,
      or 400 PIX-0087 when the requester is the customer who sent it (ask the
      payee's PSP instead — or, for the special return mechanism, see MED
      Refunds); for any other original, a requester who is not its payee is
      refused 400 PIX-0088. An on-us original settles the return synchronously
      in the ledger; an original that arrived over SPI is returned through JDPI
      first, and the ledger posting follows JD's acceptance.
    name: Refunds
  - description: >-
      **What this domain does.** Outbound PIX payments — over SPI to any other
      participant, or settled on this participant's own book when the payee is
      on-us — plus the read surface that closes the loop on them. The Refunds
      and Limits tags are part of the same flow: a devolution is a new
      transaction row, and limits are enforced here on the way out.


      **The lifecycle, and which flow settles when.** A transaction's status is
      PENDING (0), EXECUTED (2) or ERROR (-1), and the only real edge is PENDING
      → EXECUTED or ERROR. An on-us (INTRA_PSP) order settles SYNCHRONOUSLY: one
      final ledger posting, answered 201 already EXECUTED. An external CASH_OUT
      is the API's only TWO-PHASE money flow: the amount is HELD on the paying
      position as a pending ledger debit BEFORE JDPI is called; if JDPI refuses
      the order the hold is released immediately and nothing persists; if JDPI
      accepts (§8.4.1, asynchronous by design) the order persists PENDING, and a
      background reconciler polls JDPI (§8.4.2) on a short tick — settlement (JD
      processing status 9) commits the hold and flips the row EXECUTED, a
      terminal SPI error (-1) releases the hold and flips it ERROR. EXECUTED and
      ERROR are terminal. Inbound credits (CASH_IN) appear in this feed already
      EXECUTED — they settled when the webhook posted them.


      **What that means for a client.** A 201/202 on POST /v1/transactions is an
      ACCEPTED order, not settled money: poll GET
      /v1/transactions/{transactionId} until the status is terminal. PENDING
      means "SPI has not decided", never "stuck" — the reconciler acts on its
      own tick and the status read is side-effect-free. An indirect order
      (indirectId in the body) answers 202 with JD's own acknowledgement
      verbatim instead of the 201-plus-plugin-body of a direct order; handle
      both shapes.


      **Rules you cannot guess from the schemas.** (1) Amounts are integer
      centavos everywhere on this surface. (2) Send endToEndId only when you
      already hold one — from a key lookup or a QR decode — and then payee.key
      is mandatory with it (422 PIX-0037 otherwise); omit it on a manually typed
      order: SPI mints one, or this plugin does when it signs the paying
      participant's orders, and the response carries it either way. To pay a PIX
      key, look it up first with GET /v1/entries/{entryId}/lookup (§8.2.14) and
      send its payee object and its endToEndId on the order: that pair is what
      makes the payment one initiated by key. A payment by key whose payee banks
      at the paying institution is checked against DICT before it settles:
      coordinates that are not the key's account are refused 422 PIX-0033 naming
      the field, and JDPI unavailable is 503 PIX-1050. (3) The X-Idempotency
      header is REQUIRED (400 PIX-0061 without it) and is the only identifier
      that exists BEFORE the JD call, so it is what makes a retry safe on every
      branch, on-us included; a resend under a key already recorded (or a reused
      endToEndId) is refused 409 PIX-0029 and moves no money. (4) Every refusal
      is decided before the hold is taken, so a refused order moves ZERO money.
      (5) The list endpoint has NO pagination — the whole matching set arrives
      in one array, so filter narrowly; and on a CASH_IN row account_id records
      the ledger alias credited rather than a CRM account id, so correlate
      inbound rows by end_to_end_id.


      **Errors that matter.** 400 PIX-0061 missing X-Idempotency header; 409
      PIX-0029 duplicate endToEndId/X-Idempotency key; 409 PIX-0076 insufficient
      balance on the paying position; 409 PIX-0075 period limit exceeded; 409
      PIX-0078 transfer to the same account; 422 PIX-0030 non-positive amount;
      422 PIX-0033 the payee resolves to more than one account (on-us) — refused
      rather than guessed; 422 PIX-0108 a party resolves in the CRM but is bound
      to no ledger account; 404 PIX-0095 / 422 PIX-0100 unknown / not-ACTIVE
      indirect; 503 PIX-1050 JDPI unreachable (the dependency is named, and the
      order was not placed).
    name: Transactions
  - description: >-
      **What this domain is — and is not.** The INBOUND mirror of the JD
      integration: the three endpoints JDPI calls on THIS participant. It is not
      client webhook management — there is nothing to subscribe to here. The
      callers of these routes are JDPI's systems, authenticated with the same
      bearer scheme as everything else; they are documented so an integrator can
      recognize the flows, and so the counterparty configuration names the right
      paths. Only the JD Courier's credential (sourceService jd-courier), JD's
      existing application (sourceService jd-consultores) or an application the
      tenant lists as JD's (tenant_policy/jd.direct_client_ids) may call these
      routes; any other caller is 403 PIX-0005.


      **The three flows.** POST /v1/webhooks/cash-ins is the §9.3.2 inbound
      credit: money received by this participant or by an indirect it serves.
      POST /v1/webhooks/refunds is the §9.3.3 payee-bank-initiated refund of a
      payment this participant SENT: JD has already executed the return when
      this arrives. A MED refund (codes BE08 and FR01) arrives on the same route
      and credits the same original payer, booked on the MED clearing account.
      POST /v1/webhooks/validates is the §9.3.1 synchronous account validation:
      a preflight the payer's PSP runs before sending money.


      **Money arrives in REAIS here.** These bodies are authored by JD, so their
      money fields are JSON numbers in reais (converted to integer centavos at
      the boundary) — the mirror exception to the API-wide centavos rule.
      Everything this API itself answers or persists is centavos.


      **Acknowledged is not credited.** The §9.3.2/§9.3.3 success
      acknowledgement carries the triad idReqJdPi / idCreditoSgct /
      dtHrCreditoSgct, and the field that says money landed is idCreditoSgct.
      The one 200 WITHOUT it is the short-circuit for a payer settled by BACEN
      itself (ISPB 99999), which acknowledges without crediting. Refusals are
      ordinary coded HTTP errors — this surface does not hide a refusal inside a
      200.


      **How a cash-in resolves, in order.** BACEN payer → acknowledge without
      credit. Receiver on this participant's OWN ISPB → own-book credit, located
      by the ADDRESSED coordinates (branch + account number; the receiver
      document is cross-checked, not used to search — a divergence refuses
      rather than re-routes). Receiver ISPB matching an ACTIVE indirect
      participant → credit to that institution's settlement position, with the
      delivery notice recorded in the same unit of work. Anything else — an ISPB
      this participant does not serve — is REFUSED 404 PIX-0119; money is never
      parked or blindly posted. The credit is posted to the ledger BEFORE the
      acknowledgement is returned, and redelivery is deduplicated on endToEndId
      (409 PIX-0029 names a replay of a different payload; an identical replay
      of a settled credit is acknowledged idempotently). Other refusals name
      what failed to resolve: 404 PIX-0115 no account at the addressed
      coordinates, 409 PIX-0116 the coordinates resolve ambiguously, 409
      PIX-0117 the addressed account belongs to a different holder than the
      payload names, 409 PIX-0118 the account cannot be credited.


      **The refund leg holds a PARK.** A returned payment whose original is
      already EXECUTED credits the original payer immediately. One whose
      original is still PENDING (the outbound settlement race) is acknowledged
      200 and PARKED durably — the acknowledgement's idCreditoSgct carries the
      park id — and a background sweep completes the credit once the original
      settles, or escalates it if the original ends in ERROR.


      **Validation always answers 200.** Every §9.3.1 outcome is a 200 whose
      body carries the verdict and reason: DUPL for a second payment of a
      charge, paid within 24h or held in flight by another order (never for a
      static QR, tpIniciacao 2 or 10, which takes any number of payments), BE17
      for a payer mismatch on the referenced charge, AC03 for an account that
      does not resolve, BE01 for a document that diverges from the account's
      holder, AC07 / AC06 for an account its ledger holds closed / blocked. An
      HTTP error from this route means infrastructure, never "account invalid".
    name: Webhooks
paths:
  /v1/transactions:
    post:
      tags:
        - Transactions
      summary: Create a PIX transaction
      description: >-
        Creates an outbound PIX payment. What happens next depends on where the
        payee is, and the two branches answer with different statuses and
        different bodies — a client has to handle both.


        An on-us payee (payee.ispb equal to this participant's own ISPB, on a
        direct order) settles SYNCHRONOUSLY as an INTRA_PSP ledger transfer and
        answers 201 with the transaction already EXECUTED. The account credited
        is the one payee.branch, payee.accountNumber and payee.accountDigit
        name, and it must belong to payee.document (422 PIX-0134). On a payment
        by key (payee.key) those coordinates are first checked against DICT
        (§8.2.14, asked as the payer; JDPI answers a key of this institution
        from its own base): a field the order states differently from the
        account DICT binds the key to is refused 422 PIX-0033 naming that field
        (the branch is compared by value, so "1" and "0001" name the same
        branch, here and in the paying participant's records), a key DICT does
        not hold is 404 PIX-1011, and JDPI unavailable is 503 PIX-1050 — all
        before anything is held. Send the payee object GET
        /v1/entries/{entryId}/lookup answered and it matches. Any other payee
        settles over SPI in TWO PHASES: the amount is first HELD on the paying
        position as a pending ledger debit, and only then is the order submitted
        to JDPI (§8.4.1), which is asynchronous by design — nothing has settled
        when the call returns. A direct order answers 201 with the transaction
        PENDING; an order routed through a registered indirect (indirectId in
        the body) answers 202 carrying JD's own §8.4.1 acknowledgement
        byte-for-byte when JDPI returns one, whose idReqJdPi is the handle the
        outcome is read with, and 201 PENDING with this plugin's body when
        JDPI's answer proves nothing. Either way, poll GET
        /v1/transactions/{transactionId}: a background reconciler consults JDPI
        §8.4.2 and then commits or cancels the hold, and the money is not
        settled until the status says so.


        WHAT indirectId ACTUALLY MOVES, because it is more than a label. This
        participant may serve INDIRECT participants — other institutions
        registered here with POST /v1/indirects that reach SPI through this
        participant's ISPB. Naming one on an order changes THREE things at once:
        the amount is held on that institution's `@pi_{ispb}` settlement
        position instead of on the payer's own, the persisted order is stamped
        with that institution so it appears in GET
        /v1/indirects/{indirectId}/transactions, and the response shape changes
        from 201-plus-plugin-body to 202-plus-JD-body whenever JDPI acknowledges
        the order. The identifier is ROUTING DATA, not a credential: this
        participant authenticates you, and guaranteeing that the order really
        belongs to that institution is your responsibility, not this API's.


        WHO PAYS AN INDIRECT ORDER. An indirect keeps its customers in its own
        core, never in this participant's books, so the ledger counterparty of
        its order is always its `@pi_{ispb}` position. The indirect DECLARES the
        customer who pays in payer (document, name, branch, accountNumber,
        accountDigit, accountType): this plugin reads no record of it and sends
        that block to JD as the payer of the order, on the indirect's ISPB,
        exactly as sent. payer is refused 400 PIX-0061 on a direct order,
        together with accountId, or with a document that is not a CPF or CNPJ;
        an indirect order with neither is 400 PIX-0061 naming payer; a declared
        accountType 4 (Conta PI) is 422 PIX-0098. Naming the payer by accountId
        on an indirect order is DEPRECATED: it names a customer of THIS
        participant, and it is accepted, unchanged, only when this participant's
        own credential sends the order — when an Access Manager partner is
        behind the request it is refused 400 PIX-0061 naming accountId, so a
        partner confined to one indirect cannot present another customer as the
        payer nor spend that customer's limits. An order with a declared payer
        runs no account limit check: its customer's limits are the indirect's,
        kept in its own core, and the `@pi_{ispb}` balance the hold checks
        bounds it.


        ⚠️ indirectId IS REFUSED 422 PIX-0111 WHILE THIS TENANT'S
        INDIRECT-PARTICIPANTS FEATURE IS SWITCHED OFF, and the refusal names the
        setting an operator has to turn on. The order is never quietly executed
        as a DIRECT one: that would hold the amount on the payer's own position
        instead of the institution's `@pi_{ispb}`, so the money would leave an
        account you never named, behind a 201. The refusal is decided before the
        payer is read, so nothing is held and no order is persisted. An order
        carrying NO indirectId is unaffected.


        When the order reaches its outcome, an indirect order may ALSO push a
        NOTICE to the endpoint that registration carries (delivery.endpointUrl),
        queued by the background reconciler once JD's terminal outcome is known
        — an HTTPS POST forwarding JD's own result body verbatim, carrying
        X-Lerian-Signature ('sha256=' followed by the hex HMAC-SHA256 of the
        exact body bytes under the registration's shared secret) and
        X-Lerian-Timestamp. **Do not build on the notice arriving.** No notice
        is queued at all when this deployment has no outbound queue configured,
        and none is queued when the outcome carries no JD result body to forward
        — an order cancelled locally, without a JD answer, is exactly that case.
        Delivery of a notice that WAS queued is AT-LEAST-ONCE and can still fail
        permanently while the payment stands. So the institution must dedup on
        the end-to-end id and treat GET /v1/indirects/{indirectId}/transactions,
        not the notice, as the record of truth: it is the only place an outcome
        whose notice was never queued becomes visible. A direct order pushes no
        notice at all.


        End-to-end ids: send endToEndId only when you already hold one (from a
        key lookup or a QR decode), and then payee.key is mandatory with it.
        Omit it on a manually typed order: SPI mints one, or this plugin does
        when it signs the paying participant's orders — the response carries the
        value either way. A QR decode is NOT a key lookup: to pay a decoded QR,
        send the qrCodeType POST /v1/qrcodes/decode answered, together with its
        endToEndId and payee.key, or the order goes out as a payment by key and
        the payee cannot conciliate it (JDPI §8.4.1: tpIniciacao 2 for STATIC, 3
        for DYNAMIC). qrCodeType is what makes it a QR payment; txId (sent as
        idConciliacaoRecebedor, verbatim, never trimmed) follows its type:
        optional on STATIC, required on DYNAMIC. An invalid combination is
        refused 400 PIX-0061 naming the field, before anything is held: txId
        without qrCodeType, qrCodeType without payee.key or endToEndId, a STATIC
        txId that is neither *** nor up to 25 alphanumeric characters (JDPI
        §8.4.1; a static QR may decode to one, e.g. TX-001, since §8.3.1/§8.3.3
        state no charset, and such a txId cannot be sent), a DYNAMIC txId
        missing or not 26 to 35 alphanumeric characters. The two fields reach
        SPI orders only: an on-us payee and a transfer to another core of the
        same ISPB ignore them. Idempotency: the X-Idempotency header is
        REQUIRED, and it is what makes a retry safe on every branch, on-us
        included: once an order is recorded under a key, a resend under that key
        is refused 409 PIX-0029 and moves no money. Keys are scoped to the payer
        (the organization, plus the indirect participant on an indirect order);
        a new order needs a new key. Amounts are integer centavos.


        Every refusal below is decided before the hold is taken, so it moves
        ZERO money, except the cross-core answers PIX-0145, PIX-0146 and
        PIX-0149, which come after the hold and release it; when JDPI refuses
        the order after the hold exists, the call answers the refusal, the hold
        is released and the order stays in GET /v1/transactions with status
        ERROR — or PENDING, when the ledger does not confirm the release, until
        the background reconciler resolves it; when JDPI's answer does not prove
        a refusal (a timeout, a 5xx, a 408, 409 or 422 — except JD's
        payment-signature refusals JDPISPI017 and JDPISPI018, which prove one
        whatever status carries them and are never re-sent), the hold is kept
        and the order answers 201 PENDING with this plugin's body, an indirect
        order included, its final status coming later. The same release follows
        409 PIX-0136, refused before JDPI is called when the paying
        participant's payment-order signing settings are written but cannot sign
        (a setting missing, an algorithm this plugin does not sign with, a key
        that does not fit it, or a certificate that is not the key's own); the
        message names the setting, and nothing reaches JDPI unsigned. Refusals:
        409 PIX-0029 when this endToEndId or X-Idempotency key was already used
        by an order that may have moved money, and 409 PIX-0133 when that order
        was refused and moved none (send a new order under a new key); 409
        PIX-0076 when the paying position lacks the amount; 422 PIX-4009 when
        the ledger itself refuses the hold or the on-us posting for lack of
        funds (a race past PIX-0076, or an overdraft limit it would exceed), 422
        PIX-4007 when it refuses a same-ledger on-us payment because an account
        on it has no balance it can post to (none opened in that ledger, or a
        deleted one), 400 PIX-4005 when it refuses one because an account on it
        may not send or receive or is blocked, and 422 PIX-4018 when the
        client's own transaction rules deny the posting — the ledger refused, so
        nothing moved and the order stays ERROR;409 PIX-0078 on a transfer to
        the same account; 409 PIX-0075 when the account's period limit is
        exceeded; 422 PIX-0030 on a non-positive amount; 422 PIX-0162 when
        feeContext names a label no fee package of the payer's ledger selects
        on, enabled or not, or that ledger does not price Pix by fee package;
        422 PIX-0037 when endToEndId arrives without payee.key; 422 PIX-0108
        when the payer — or, on an indirect order, the indirect's `@pi` —
        resolves in the CRM but is not bound to a ledger account; 422 PIX-0111
        when an indirectId is supplied while this deployment's
        indirect-participants feature is off (naming the setting to enable — the
        order is refused, never quietly paid from the payer's own account), 404
        PIX-0095 for an unknown or malformed indirectId and 422 PIX-0100 when
        the indirect it names is not ACTIVE; 422 PIX-0127 when this deployment
        acts as SEVERAL direct participants and the order names none of them in
        payerIspb, and 422 PIX-0128 when the one it names is not among them;
        when the payee banks at the PAYING participant — the order would
        normally settle internally, never touching SPI — and that participant
        has declared its ISPB shared with another core, the ownership map says
        which books hold the account the order names (payee.branch,
        payee.accountNumber and payee.accountDigit; a payment account,
        accountType 3, by its account alone), asked before the payee is looked
        up. When the OTHER core holds it, the order is a cross-core transfer,
        never sent over SPI: the amount is held on the payer's account and the
        order is relayed to that core, answering 201 EXECUTED once it credited
        the payee, 201 PENDING while its answer is unknown (the hold stays and
        the background worker resends and settles it; poll GET
        /v1/transactions), 422 PIX-0145 when it refused the credit and 503
        PIX-0146 when the order never reached it — both release the hold, so
        nothing was debited, and the order stays in GET /v1/transactions with
        status ERROR (send it again under a new X-Idempotency key); and 409
        PIX-0149 when any fee in the package priced on the cross-core route
        (this leg to the other core of the same participant, priced like a Pix
        sent to another bank) is configured to deduct from the amount instead of
        being charged on top (an operator setting) — the applied package is
        known only once the hold is posted, so this refusal comes after the hold
        and before anything is relayed: the hold is released and the order stays
        ERROR, or PENDING until the background worker finishes a release the
        ledger did not confirm; nothing was debited; and 409 PIX-0150 when the
        paying ledger holds no @intercore account, the clearing account a
        cross-core transfer moves through (an operator setting): the ledger
        refuses the hold, nothing was debited, the order stays ERROR and the
        message names the organization and ledger to create it in. Otherwise:
        422 PIX-0129 when the map holds that account nowhere, 422 PIX-0132 when
        the order's account cannot be used to ask (a blank account, a blank
        branch on anything but a payment account, or one the map refuses as
        malformed — a retry changes nothing), 503 PIX-0130 when it could not
        answer (safe to retry: nothing was created) and 502 PIX-0131 when it
        answered in a form that cannot be acted on; each of these four is
        refused before anything is held and is NOT rerouted over SPI; an on-us
        payment WITHOUT payee.key is a payment by bank details, and it is
        credited on the account payee.branch, payee.accountNumber and
        payee.accountDigit name — number and digit together, exactly the account
        an interbank Pix carries — which must belong to payee.document, as the
        receiving institution checks on an interbank Pix: 404 PIX-2016 when the
        paying participant holds no such account, 422 PIX-0134 when it belongs
        to someone else, 422 PIX-0033 when no account is typed, 422 PIX-0108
        when it is not bound to a ledger account (a payment account, accountType
        3, is looked up by its account alone); an on-us payment WITH payee.key
        is credited on the account payee.branch, payee.accountNumber and
        payee.accountDigit name once DICT has confirmed them, checked exactly as
        a payment by bank details (404 PIX-2016, 422 PIX-0134), while an order
        naming no account is 422 PIX-0033; 422 PIX-0108 when that payee is not
        bound to a ledger account; 422 PIX-0102 when payerIspb is supplied on an
        indirect order and is not the participant recorded at that indirect's
        registration; 409 PIX-0105 when the ledger the money leaves from
        declares no accounting route for the direction; when the payer or the
        on-us payee cannot be used as the order addresses it, nothing is
        reserved and the answer names what refused: 422 PIX-0137 when the
        account is held in a ledger that is not configured for Pix on the paying
        participant (pay from or to an account on a configured ledger, or have
        the operator add that ledger to the Pix setup), 422 PIX-0138 when the
        account's record does not say which ledger holds it, 422 PIX-0139 when
        the payer's record names a different institution than the one paying,
        422 PIX-0141 when, on an indirect order, the payer account is not in the
        ledger the indirect is mounted on, and 409 PIX-0140 when the indirect is
        mounted on books no longer configured for Pix (an operator setting); a
        refusal of the payer names the payer account (accountId) in its message,
        while a refusal of the on-us payee — PIX-0137 or PIX-0138 — names no
        account, because on a payment by key the payee's account is one you
        never saw, so read it as the payee the order addressed; 400 PIX-0061
        when the X-Idempotency header is missing, blank or over 255 bytes, when
        a direct order has no accountId, when payer is sent where it does not
        belong or with a document that is not a CPF or CNPJ, when an indirect
        order has neither payer nor accountId, when a partner names accountId on
        an indirect order, when an accountType is outside the PIX domain 0..4,
        or when feeContext is malformed or sent with indirectId. Called with a
        partner credential, the order is also decided by that partner's own
        rules for the ledger and the CRM this plugin calls to serve it: 403
        PIX-4019 when Midaz refuses the partner and 403 PIX-2025 when the CRM
        does, the message naming the reason (other_tenant, suspended,
        no_longer_valid or not_allowed) — grant the partner the missing
        permission on that service; a partner holding no grant for those
        services is decided by its Pix grant alone. On an indirect order a JD
        refusal is passed back with JD's own status and body instead of a
        problem+json. An on-us payee who banks at the paying participant but in
        a DIFFERENT ledger of it is served rather than refused: the amount is
        reserved on the payer's ledger, credited on the payee's ledger, and the
        reserve is then committed — so the order answers EXECUTED only once both
        legs landed. Both on-us shapes persist their transaction before the
        first posting, so their failures are not invisible: an order the ledger
        refuses answers an error AND leaves a transaction you will find in GET
        /v1/transactions with status ERROR (it does not count against the
        account's period limit: only a hold that reached the ledger does); a
        same-ledger order whose posting the ledger leaves unknown answers 5xx
        and stays PENDING until the reconcile worker finds the posting and
        settles it EXECUTED — a posting the ledger does not show yet never fails
        the order, because the ledger may record a posting after answering for
        it; and a cross-ledger order whose credit the payee's ledger has not yet
        confirmed delivered is ACCEPTED and still settling: it answers 201 with
        status PENDING, the money stays held, and the reconcile worker completes
        it — poll GET /v1/transactions rather than retrying it as a fresh
        payment. NOT every failure on that branch became a 201, and the
        exception matters because the money has already moved: when the credit
        HAS landed and the ledger then leaves the outcome of CLOSING the hold
        unknown — the settle failed, or a release could not be proved — the
        order still answers 5xx AND still leaves the transaction PENDING. So a
        5xx here never means nothing happened. Poll GET /v1/transactions; if you
        retry, retry with the SAME X-Idempotency key, because a fresh key is a
        second payment.
      operationId: createTransaction
      parameters:
        - description: >-
            Idempotency key for this payment order: any stable string you
            choose, up to 255 bytes, sent as the X-Idempotency request header
            (the same header, by the same name, that MED writes and the Midaz
            ledger take). REQUIRED: omitting it, sending only whitespace, or
            sending more than 255 bytes is refused 400 PIX-0061 before anything
            is read, held or sent. Send the SAME value again to retry the SAME
            order: once an order is recorded under the key, a resend is answered
            409 PIX-0029 and moves no money, whether that order went to SPI or
            settled on-us, so read its outcome with GET /v1/transactions. Keys
            are scoped to the payer: the organization, plus the indirect
            participant on an indirect order. A new order needs a new key.
            BREAKING CHANGE: this replaces the optional body field
            clientRequestId, which no longer exists.
          in: header
          name: X-Idempotency
          required: true
          schema:
            description: >-
              Idempotency key for this payment order: any stable string you
              choose, up to 255 bytes, sent as the X-Idempotency request header
              (the same header, by the same name, that MED writes and the Midaz
              ledger take). REQUIRED: omitting it, sending only whitespace, or
              sending more than 255 bytes is refused 400 PIX-0061 before
              anything is read, held or sent. Send the SAME value again to retry
              the SAME order: once an order is recorded under the key, a resend
              is answered 409 PIX-0029 and moves no money, whether that order
              went to SPI or settled on-us, so read its outcome with GET
              /v1/transactions. Keys are scoped to the payer: the organization,
              plus the indirect participant on an indirect order. A new order
              needs a new key. BREAKING CHANGE: this replaces the optional body
              field clientRequestId, which no longer exists.
            examples:
              - order-2026-09-25-0001
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateTransactionBody'
        required: true
      responses:
        '201':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateTransactionResponse'
          description: Created
        '202':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateTransactionAcceptedResponse'
          description: >-
            Accepted for asynchronous settlement. Returned on the arrangement
            (indirect-participant) path when JDPI acknowledges the order, the
            body being JD's own §8.4.1 acknowledgement passed through verbatim;
            an indirect order whose JDPI answer proves nothing answers 201
            PENDING instead. Nothing has settled: the amount is reserved on the
            ordering participant's position and the outcome is obtained by
            polling JDPI §8.4.2 with the returned idReqJdPi.
        '400':
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Detail'
          description: Bad Request
        '413':
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Detail'
          description: Request Entity Too Large
        '500':
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Detail'
          description: Internal Server Error
        '502':
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Detail'
          description: >-
            The ownership map answered in a form that cannot be acted on
            (PIX-0131). Nothing was reserved.
        '503':
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Detail'
          description: >-
            A dependency could not answer. Only PIX-0130 (the ownership map
            could not answer) and PIX-0146 (a cross-core order never reached the
            payee's core, and its hold was released) guarantee nothing was
            debited. Any other 503 may leave the transaction PENDING with money
            already moved — poll GET /v1/transactions, and retry only with the
            SAME X-Idempotency key, because a fresh key is a second payment.
        default:
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Detail'
          description: Error
components:
  schemas:
    CreateTransactionBody:
      additionalProperties: false
      properties:
        accountId:
          description: >-
            The Midaz ledger account id of the payer, a customer of the paying
            direct participant. REQUIRED on a direct order (absent or blank is
            400 PIX-0061). On an order carrying indirectId it is DEPRECATED in
            favour of payer: an indirect keeps its customers in its own core, so
            the money always leaves its @pi position and the payer is the
            customer it declares in payer. accountId is still accepted there,
            unchanged, when the direct participant's own credential sends the
            order, and refused 400 PIX-0061 when an Access Manager partner is
            behind the request. Sending it together with payer is 400 PIX-0061.
          examples:
            - 019a1b2c-3d4e-7f60-8a9b-0c1d2e3f4a5b
          type: string
        amount:
          description: Transaction amount in centavos (an integer, e.g. 10050 = R$ 100,50).
          examples:
            - 10050
          format: int64
          type: integer
        description:
          description: Free-text payment description.
          examples:
            - Invoice 42
          type: string
        endToEndId:
          description: >-
            SPI end-to-end id. Omit ONLY for a manually-typed payment order: per
            JDPI §8.4.1 the id does not exist yet and is generated by SPI on
            this call. If you obtained one from POST /v1/qrcodes/decode (§8.3.3)
            or from GET /v1/entries/{entryId}/lookup (§8.2.14) you MUST send it:
            omitting it makes SPI mint a DIFFERENT id, and on a payment by key
            it makes the order go out as manually typed. The endToEndId alone
            does NOT make an order a QR payment: a Pix paid from a decoded QR
            must also send qrCodeType (and txId as qrCodeType requires: optional
            on STATIC, required on DYNAMIC), or it goes out as a payment by key
            and the payee cannot conciliate it.
          examples:
            - E1234567890
          type: string
        feeContext:
          description: >-
            Optional fee label you choose. The payer-side ledger posting carries
            it, so the fee package of the payer's ledger whose metadataSelector
            names this feeContext prices the order. Format: a lowercase letter,
            then up to 49 lowercase letters, digits or underscores; never
            personal data. Refused 400 PIX-0061 when malformed or sent with
            indirectId. Refused 422 PIX-0162, before anything is held, unless a
            fee package of the payer's ledger, enabled or not, selects on it and
            that ledger prices Pix by fee package.
          examples:
            - pix_salario
          type: string
        indirectId:
          description: >-
            Optional registered-indirect identifier (UUID) routing this outbound
            order through an indirect participant's PIX position. Omit for a
            direct order. Validated server-side before any money moves; unknown
            or inactive is rejected. Refused 422 PIX-0111, naming the setting to
            enable, while this deployment's indirect-participants feature is off
            — the order is never executed as a direct one, which would hold the
            funds on the payer's own account instead of the indirect's PIX
            position.
          examples:
            - 3f2504e0-4f89-41d3-9a0c-0305e82c3301
          format: uuid
          type: string
        payee:
          $ref: '#/components/schemas/PayeeBody'
          description: The recipient bank data.
        payer:
          $ref: '#/components/schemas/OrderPayerBody'
          description: >-
            The customer of the indirect participant who pays this order, as the
            indirect declares it. Only with indirectId, and required there
            unless the legacy accountId is sent instead: an indirect keeps its
            customers in its own core, so this plugin reads no record of them
            and sends this block to JD as the payer of the order, on the
            indirect's ISPB, while the money leaves the indirect's @pi position.
            Refused 400 PIX-0061 on a direct order, together with accountId, or
            with a document that is not a CPF or CNPJ.
        payerIspb:
          description: >-
            The ISPB of the institution the money leaves from. This deployment
            may act as SEVERAL direct SPI participants — one ISPB each, each
            with its own books — and this field is the only thing on the order
            that says which of them pays. OPTIONAL while it acts as a single
            participant: omit it and that one pays. REQUIRED once it acts as
            several — omitted is 422 PIX-0127, and an ISPB this deployment does
            not act as is 422 PIX-0128. It is ROUTING DATA you supply and
            guarantee, exactly like indirectId: never a credential, never read
            from a header or a path, and it never widens what your token can
            reach. It also decides what counts as on-us — a payee on the PAYING
            institution ISPB settles as an internal transfer, a payee on a
            sibling institution of this same deployment is an ordinary Pix over
            SPI. On an order carrying indirectId it must be blank or the
            participant recorded at that indirect's registration, which is not
            necessarily the deployment default one (422 PIX-0102). Send it as an
            absent key, not an empty string; an empty value is refused 400
            PIX-0061.
          examples:
            - '12345678'
          pattern: ^[0-9A-Z]{8}$
          type: string
        priority:
          description: Numeric eTransactionPriority (1=PRIMARY,2=SECONDARY).
          examples:
            - 1
          format: int64
          type: integer
        qrCodeType:
          description: >-
            The qrCodeType POST /v1/qrcodes/decode answered, copied verbatim, on
            a Pix paid from a QR. It makes the order go out as a QR payment
            (JDPI §8.4.1 tpIniciacao 2 for STATIC, 3 for DYNAMIC) instead of a
            payment by key. Requires payee.key and endToEndId, both as the
            decode answered them. Omit it on a key or a manually typed payment.
            Validated before anything is held: an invalid combination is refused
            400 PIX-0061 naming the field. When the payee banks at the paying
            institution (an on-us transfer sends no order to SPI) it routes
            nothing: it is recorded as the initiation type (tpIniciacao) of the
            TRCK.002 report that on-us Pix owes Bacen. Ignored on a transfer to
            another core of the same ISPB.
          enum:
            - STATIC
            - DYNAMIC
          examples:
            - DYNAMIC
          type: string
        txId:
          description: >-
            The txId POST /v1/qrcodes/decode answered, copied verbatim and never
            trimmed (whitespace is refused 400 PIX-0061); sent to JDPI as
            idConciliacaoRecebedor so the payee conciliates the payment. Only
            with qrCodeType (alone it is refused 400 PIX-0061). STATIC:
            optional, up to 25 alphanumeric characters ([a-zA-Z0-9]); the static
            default *** is accepted and sent as absent. A static QR may decode
            to a txId outside that band (e.g. TX-001: JDPI §8.3.1/§8.3.3 state
            no charset, §8.4.1 does); such a QR cannot be paid as a QR payment,
            and sending its txId is refused 400 PIX-0061 before anything is
            held. DYNAMIC: required, 26 to 35 alphanumeric characters.
          examples:
            - KJ8H2ZQ0RX4T7W1N9C3V5B6M8P
          type: string
      required:
        - amount
        - payee
      type: object
    CreateTransactionResponse:
      additionalProperties: false
      properties:
        amount:
          description: Transaction amount in centavos.
          examples:
            - 10050
          format: int64
          type: integer
        description:
          description: Payment description.
          examples:
            - Invoice 42
          type: string
        endToEndId:
          description: The SPI end-to-end id.
          examples:
            - E1234567890
          type: string
        flow:
          description: Numeric eTransactionFlow (2=CASH_OUT,3=INTRA_PSP).
          examples:
            - 2
          format: int64
          type: integer
        id:
          description: The created transaction id.
          examples:
            - d1f9c0a2-...
          type: string
        jdpiRequestId:
          description: The JDPI request id (external CASH_OUT).
          examples:
            - REQ-123
          type: string
        priority:
          description: Numeric eTransactionPriority.
          examples:
            - 1
          format: int64
          type: integer
        status:
          description: eTransactionStatus name.
          examples:
            - PENDING
          type: string
      required:
        - id
        - status
        - amount
      type: object
    CreateTransactionAcceptedResponse:
      additionalProperties: true
      properties:
        dtHrReqJdPi:
          description: The JD request timestamp.
          examples:
            - '2026-01-01T00:00:00.000Z'
          type: string
        endToEndId:
          description: The SPI end-to-end id JD assigned to the order.
          examples:
            - E1234567890
          type: string
        idReqJdPi:
          description: >-
            The JD request id. Poll JDPI §8.4.2 with this id to learn the
            settlement outcome.
          examples:
            - 45F763C6-7487-4363-9406-A1DE2A9636D3
          type: string
        idReqSistemaCliente:
          description: The client request id JD echoes back (the idempotency key, GUID).
          examples:
            - 9F4C2A10-0000-4000-8000-000000000001
          type: string
        tpCanal:
          description: The JD settlement-channel discriminator, when JD sends it.
          examples:
            - 2
          format: int64
          type: integer
      required:
        - idReqSistemaCliente
        - idReqJdPi
        - endToEndId
        - dtHrReqJdPi
      type: object
    Detail:
      additionalProperties: true
      properties:
        code:
          description: >-
            Stable, machine-readable domain error code scoped to the emitting
            service (format: <SERVICE>-NNNN).
          type: string
        detail:
          description: >-
            A human-readable explanation specific to this occurrence of the
            problem.
          examples:
            - Property foo is required but is missing.
          type: string
        errors:
          description: Optional list of individual error details
          items:
            $ref: '#/components/schemas/ErrorDetail'
          type:
            - array
            - 'null'
        instance:
          description: >-
            A URI reference that identifies the specific occurrence of the
            problem.
          examples:
            - https://example.com/error-log/abc123
          format: uri
          type: string
        status:
          description: HTTP status code
          examples:
            - 400
          format: int64
          type: integer
        title:
          description: >-
            A short, human-readable summary of the problem type. This value
            should not change between occurrences of the error.
          examples:
            - Bad Request
          type: string
        type:
          default: about:blank
          description: A URI reference to human-readable documentation for the error.
          examples:
            - https://example.com/errors/example
          format: uri
          type: string
        upstream:
          $ref: '#/components/schemas/Upstream'
          description: >-
            RFC 9457 extension member: the error a proxied third-party provider
            reported. Absent unless the emitting service explicitly surfaced
            one.
      type: object
    PayeeBody:
      additionalProperties: false
      properties:
        accountDigit:
          description: >-
            Recipient account check digit, appended to accountNumber with no
            separator to form the payee's account. Send it empty when the
            account has no check digit or when accountNumber already includes
            it; never send the digit in both. See accountNumber.
          examples:
            - '7'
          type: string
        accountNumber:
          description: >-
            Recipient account number. The payee's account is accountNumber
            followed by accountDigit, with no separator: that is the value sent
            to JD on a payment to another institution, and the value looked up
            on a payment to a payee at your own institution (ispb equal to the
            paying institution's). In that case the account is searched, as that
            exact string, among the accounts registered in the CRM bank details
            of your holders, so the CRM must store the account number and its
            check digit together, with no hyphen or space. Either split
            addresses the same account: 1234567 with accountDigit 8, or 12345678
            with accountDigit empty, both look up 12345678. A digit added or
            left out addresses a different account. No account registered under
            that value is 404 PIX-2016; an account held by someone other than
            payee.document is 422 PIX-0134.
          examples:
            - '123456'
          type: string
        accountType:
          description: >-
            Recipient JDPI tpConta (0=Conta Corrente, 1=Conta Salario, 2=Conta
            Poupanca, 3=Conta de Pagamento, 4=Conta PI). REQUIRED and never
            defaulted: JDPI section 8.4.1 marks recebedor.tpConta mandatory and
            its domain has no 'unknown' member, so sending 0 for an account you
            have not identified asserts 'Conta Corrente' about a savings or
            payment account and settles the money against a false type. Take it
            from decode-QRCode (section 8.3.3) or from GET
            /v1/entries/{entryId}/lookup (section 8.2.14), which both return it,
            or from the recipient details on a manually-typed order.
          examples:
            - 0
          format: int64
          type: integer
        branch:
          description: >-
            Recipient agency/branch, without check digit. For a payee at your
            own institution it must match the branch registered for that account
            in the CRM bank details (leading zeros are not significant, so 1
            matches 0001); it is ignored for a payment account (accountType 3),
            which is located by its account alone.
          examples:
            - '0001'
          type: string
        document:
          description: Recipient document (CPF/CNPJ).
          examples:
            - '12345678909'
          type: string
        ispb:
          description: Recipient participant ISPB (equal to the plugin ISPB routes on-us).
          examples:
            - '12345678'
          type: string
        key:
          description: Recipient PIX key, when the payment targets a key.
          examples:
            - foo@bar.com
          type: string
        name:
          description: Recipient holder name.
          examples:
            - Jane Doe
          type: string
      required:
        - ispb
        - document
        - accountNumber
        - accountDigit
        - accountType
      type: object
    OrderPayerBody:
      additionalProperties: false
      properties:
        accountDigit:
          description: >-
            The payer's account check digit, appended to accountNumber with no
            separator. Send it empty when accountNumber already includes it.
          examples:
            - '7'
          type: string
        accountNumber:
          description: >-
            The payer's account number at the indirect. Sent to JD followed by
            accountDigit, with no separator.
          examples:
            - '123456'
          maxLength: 20
          minLength: 1
          type: string
        accountType:
          description: >-
            The payer's JDPI tpConta (0=Conta Corrente, 1=Conta Salario, 2=Conta
            Poupanca, 3=Conta de Pagamento). 4 (Conta PI) is the direct
            participant's own-funds account and is refused 422 PIX-0098 before
            anything is held.
          examples:
            - 0
          format: int64
          type: integer
        branch:
          description: The payer's agency/branch at the indirect, without check digit.
          examples:
            - '0001'
          type: string
        document:
          description: >-
            The payer's document (CPF/CNPJ), mask allowed. Sent to JD canonical
            (digits, and the letters of an alphanumeric CNPJ). Anything that is
            not a CPF of 11 digits or a CNPJ of 14 characters is refused 400
            PIX-0061 before anything is held.
          examples:
            - '52998224725'
          type: string
        name:
          description: The payer's holder name, sent to JD as the payer's name.
          examples:
            - Jane Doe
          minLength: 1
          type: string
      required:
        - document
        - name
        - accountNumber
        - accountDigit
        - accountType
      type: object
    ErrorDetail:
      additionalProperties: false
      properties:
        location:
          description: >-
            Where the error occurred, e.g. 'body.items[3].tags' or
            'path.thing-id'
          type: string
        message:
          description: Error message text
          type: string
        value:
          description: The value at the given location
      type: object
    Upstream:
      additionalProperties: false
      properties:
        code:
          description: The upstream provider's own error code, verbatim.
          examples:
            - E4001
          type: string
        message:
          description: >-
            The upstream provider's own error message, verbatim (bounded, never
            its raw response body).
          examples:
            - account not found at provider
          type: string
      type: object
  securitySchemes:
    BearerAuth:
      bearerFormat: JWT
      description: JWT bearer token issued by the identity provider.
      scheme: bearer
      type: http

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.