> ## 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 refund

> Creates a PIX refund against an executed transaction. Bacen makes the refund the RECIPIENT's operation, so the caller must be the party that RECEIVED the original payment: the requesting accountId's document has to equal the original payee's document. A refund of a Pix an indirect received takes its refunder from the original payee and needs no accountId; a partner naming one there is refused 400 PIX-0061. The original payer cannot refund a payment it sent — that is the MED/fraud path, not this one.

Identify the original with BOTH transactionId (the local UUID) and endToEndId, and it must still be EXECUTED. Partial refunds are allowed and they ACCUMULATE: the amount is checked against the original amount minus everything already refunded, under a row lock on the original, so two concurrent refunds cannot together exceed it. An on-us original is refunded as a synchronous ledger reversal from the refunder to the original payer; a payment received from another institution is returned over SPI: the amount is first reserved on the refunding account, then the refund is submitted to JDPI, and it answers PENDING with the money held until SPI settles it (EXECUTED, the reserve committed) or refuses it (ERROR, the reserve released) — poll GET /v1/transactions. A Pix received from an account that banks at this participant but is held in other books is returned to those books, never over SPI: the amount is held on the refunding account and the refund relayed, answering EXECUTED once those books credited the original payer, PENDING while their answer is unknown (the reconcile worker completes it — poll GET /v1/transactions), 422 PIX-0145 when they refused it and 503 PIX-0146 when they could not be reached; both release the hold, so nothing moved; 409 PIX-0149 when any fee in the package priced on the cross-core return route (this refund to the other core of the same participant, priced like a refund 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, by the reconcile worker when the ledger does not confirm the release at once, and nothing moved; 409 PIX-0150 when the refunding ledger holds no @intercore account (an operator setting): the ledger refuses the hold, nothing moved, and the message names the organization and ledger to create it in. The refund's own end-to-end id (endToEndRefundId) is filled when JD supplies it and may be empty while the refund is PENDING; an empty value is not a failure, the outcome arrives as transaction.refunded or transaction.failed. An on-us original that itself moved between two ledgers of this institution is returned the same way it was paid — a reserve in the ledger that received it, a credit in the ledger that paid, then a commit — so that one branch reports EXECUTED only after both legs landed; a refund whose credit that ledger has not yet confirmed delivered is ACCEPTED and still settling, reported PENDING with the money held, and the reconcile worker completes it — poll GET /v1/transactions rather than retrying it as a fresh refund. The exception is the same one the payment route carries: once the credit has landed, a settlement outcome the ledger leaves unknown while CLOSING the reserve still answers 5xx and still leaves the transaction PENDING, so a 5xx here never means nothing happened — poll it rather than sending a new refund under a new key. code is the return reason and is accepted only as BE08, FR01, MD06 or SL02.

Idempotency: the X-Idempotency header is REQUIRED, and it is what makes a resend safe on every branch, on-us included: once a refund is recorded under a key, a resend under that key is refused 409 PIX-0029 and moves no money — read its outcome with GET /v1/transactions. Keys are scoped to the payer (the organization, plus the indirect participant on an indirect refund); a new refund needs a new key.

A Pix received on an indirect participant's PIX position is returned by that indirect: send its indirectId, and the refund debits that indirect's position. A Pix received on a direct account is returned without one.

payerIspb optionally names the direct participant paying the refund back. Named, the original has to be booked in that participant's books, checked before the idempotency key is read and before anything is held or sent; a token confined to one participant has to name it.

Refusals: 422 PIX-0036 when no EXECUTED payment matches that (endToEndId, transactionId) pair, which is also the answer when the pair names a refund (a refund is never the original of another); 404 PIX-0147 when payerIspb names a participant, or indirectId an indirect, that does not hold the original (checked before eligibility, so it never tells the caller whether another participant's original exists or which way it went); 422 PIX-0128 for a payerIspb this deployment does not act as; 400 PIX-0087 when the original is a payment sent to another institution, or to an account held in other books of this one, and the caller is its sender; 400 PIX-0089 when it is such a payment and the caller is anyone else (only the receiving institution can return what it received); 400 PIX-0088 when the original is any other payment and the caller is not its payee; 422 PIX-0135 when indirectId is absent on a Pix received on an indirect's position; 422 PIX-0111 when the indirect-participants feature is off, 404 PIX-0095 when the indirect is not registered and 422 PIX-0100 when it is not ACTIVE, as on a payment order; 409 PIX-0075 when this amount plus the prior refunds would exceed the original; 409 PIX-0076 when the available balance of the account the refund debits (the indirect's position, for a Pix it received) is below the amount of a refund sent over SPI or to other books (nothing is reserved or sent); 409 PIX-0029 when this X-Idempotency key already names a refund of the payer, and while another refund of the same payment sent over SPI or to other books is still PENDING, or when JD answers with an earlier refund of it; 422 PIX-0030 on a non-positive amount; 409 PIX-0105 when a ledger the refund has to post in does not declare the reversal accounting routes (nothing is posted and no refund is recorded); 409 PIX-0142 when the ledger the original was booked in — or, for an on-us payment between two ledgers, the ledger it was credited in — is no longer configured for Pix on this deployment (nothing is posted and no refund is recorded; an operator has to restore that ledger to the Pix setup); 422 PIX-4009 when the ledger itself refuses the reserve or the on-us reversal for lack of funds (an overdraft limit it would exceed included), 422 PIX-4007 when it refuses a same-ledger on-us reversal 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 refund stays ERROR; 400 PIX-0061 when the X-Idempotency header is absent, blank or over 255 bytes, accountId or endToEndId is empty, transactionId is not a UUID, or code is outside the four accepted values.



## OpenAPI

````yaml /pt/openapi/v3-current/pix.yaml post /v1/refunds
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/refunds:
    post:
      tags:
        - Refunds
      summary: Create a PIX refund
      description: >-
        Creates a PIX refund against an executed transaction. Bacen makes the
        refund the RECIPIENT's operation, so the caller must be the party that
        RECEIVED the original payment: the requesting accountId's document has
        to equal the original payee's document. A refund of a Pix an indirect
        received takes its refunder from the original payee and needs no
        accountId; a partner naming one there is refused 400 PIX-0061. The
        original payer cannot refund a payment it sent — that is the MED/fraud
        path, not this one.


        Identify the original with BOTH transactionId (the local UUID) and
        endToEndId, and it must still be EXECUTED. Partial refunds are allowed
        and they ACCUMULATE: the amount is checked against the original amount
        minus everything already refunded, under a row lock on the original, so
        two concurrent refunds cannot together exceed it. An on-us original is
        refunded as a synchronous ledger reversal from the refunder to the
        original payer; a payment received from another institution is returned
        over SPI: the amount is first reserved on the refunding account, then
        the refund is submitted to JDPI, and it answers PENDING with the money
        held until SPI settles it (EXECUTED, the reserve committed) or refuses
        it (ERROR, the reserve released) — poll GET /v1/transactions. A Pix
        received from an account that banks at this participant but is held in
        other books is returned to those books, never over SPI: the amount is
        held on the refunding account and the refund relayed, answering EXECUTED
        once those books credited the original payer, PENDING while their answer
        is unknown (the reconcile worker completes it — poll GET
        /v1/transactions), 422 PIX-0145 when they refused it and 503 PIX-0146
        when they could not be reached; both release the hold, so nothing moved;
        409 PIX-0149 when any fee in the package priced on the cross-core return
        route (this refund to the other core of the same participant, priced
        like a refund 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, by the reconcile worker when the ledger does not confirm the
        release at once, and nothing moved; 409 PIX-0150 when the refunding
        ledger holds no @intercore account (an operator setting): the ledger
        refuses the hold, nothing moved, and the message names the organization
        and ledger to create it in. The refund's own end-to-end id
        (endToEndRefundId) is filled when JD supplies it and may be empty while
        the refund is PENDING; an empty value is not a failure, the outcome
        arrives as transaction.refunded or transaction.failed. An on-us original
        that itself moved between two ledgers of this institution is returned
        the same way it was paid — a reserve in the ledger that received it, a
        credit in the ledger that paid, then a commit — so that one branch
        reports EXECUTED only after both legs landed; a refund whose credit that
        ledger has not yet confirmed delivered is ACCEPTED and still settling,
        reported PENDING with the money held, and the reconcile worker completes
        it — poll GET /v1/transactions rather than retrying it as a fresh
        refund. The exception is the same one the payment route carries: once
        the credit has landed, a settlement outcome the ledger leaves unknown
        while CLOSING the reserve still answers 5xx and still leaves the
        transaction PENDING, so a 5xx here never means nothing happened — poll
        it rather than sending a new refund under a new key. code is the return
        reason and is accepted only as BE08, FR01, MD06 or SL02.


        Idempotency: the X-Idempotency header is REQUIRED, and it is what makes
        a resend safe on every branch, on-us included: once a refund is recorded
        under a key, a resend under that key is refused 409 PIX-0029 and moves
        no money — read its outcome with GET /v1/transactions. Keys are scoped
        to the payer (the organization, plus the indirect participant on an
        indirect refund); a new refund needs a new key.


        A Pix received on an indirect participant's PIX position is returned by
        that indirect: send its indirectId, and the refund debits that
        indirect's position. A Pix received on a direct account is returned
        without one.


        payerIspb optionally names the direct participant paying the refund
        back. Named, the original has to be booked in that participant's books,
        checked before the idempotency key is read and before anything is held
        or sent; a token confined to one participant has to name it.


        Refusals: 422 PIX-0036 when no EXECUTED payment matches that
        (endToEndId, transactionId) pair, which is also the answer when the pair
        names a refund (a refund is never the original of another); 404 PIX-0147
        when payerIspb names a participant, or indirectId an indirect, that does
        not hold the original (checked before eligibility, so it never tells the
        caller whether another participant's original exists or which way it
        went); 422 PIX-0128 for a payerIspb this deployment does not act as; 400
        PIX-0087 when the original is a payment sent to another institution, or
        to an account held in other books of this one, and the caller is its
        sender; 400 PIX-0089 when it is such a payment and the caller is anyone
        else (only the receiving institution can return what it received); 400
        PIX-0088 when the original is any other payment and the caller is not
        its payee; 422 PIX-0135 when indirectId is absent on a Pix received on
        an indirect's position; 422 PIX-0111 when the indirect-participants
        feature is off, 404 PIX-0095 when the indirect is not registered and 422
        PIX-0100 when it is not ACTIVE, as on a payment order; 409 PIX-0075 when
        this amount plus the prior refunds would exceed the original; 409
        PIX-0076 when the available balance of the account the refund debits
        (the indirect's position, for a Pix it received) is below the amount of
        a refund sent over SPI or to other books (nothing is reserved or sent);
        409 PIX-0029 when this X-Idempotency key already names a refund of the
        payer, and while another refund of the same payment sent over SPI or to
        other books is still PENDING, or when JD answers with an earlier refund
        of it; 422 PIX-0030 on a non-positive amount; 409 PIX-0105 when a ledger
        the refund has to post in does not declare the reversal accounting
        routes (nothing is posted and no refund is recorded); 409 PIX-0142 when
        the ledger the original was booked in — or, for an on-us payment between
        two ledgers, the ledger it was credited in — is no longer configured for
        Pix on this deployment (nothing is posted and no refund is recorded; an
        operator has to restore that ledger to the Pix setup); 422 PIX-4009 when
        the ledger itself refuses the reserve or the on-us reversal for lack of
        funds (an overdraft limit it would exceed included), 422 PIX-4007 when
        it refuses a same-ledger on-us reversal 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 refund stays ERROR; 400 PIX-0061 when the X-Idempotency
        header is absent, blank or over 255 bytes, accountId or endToEndId is
        empty, transactionId is not a UUID, or code is outside the four accepted
        values.
      operationId: createRefund
      parameters:
        - description: >-
            Idempotency key for this refund: any stable string you choose, up to
            255 bytes, sent as the X-Idempotency request header (the same
            header, by the same name, that payment orders, 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 refund: once a refund is recorded under the key, a resend
            is answered 409 PIX-0029 and moves no money, whether it 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 refund. A new refund 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 refund: any stable string you choose, up
              to 255 bytes, sent as the X-Idempotency request header (the same
              header, by the same name, that payment orders, 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 refund: once a refund is recorded under the key,
              a resend is answered 409 PIX-0029 and moves no money, whether it
              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 refund. A new refund
              needs a new key. BREAKING CHANGE: this replaces the optional body
              field clientRequestId, which no longer exists.
            examples:
              - refund-2026-09-29-0001
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RefundBody'
        required: true
      responses:
        '201':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RefundResponse'
          description: Created
        '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
        default:
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Detail'
          description: Error
components:
  schemas:
    RefundBody:
      additionalProperties: false
      properties:
        accountId:
          description: >-
            The Midaz ledger account id of the requesting account (the original
            payee), a customer of the direct participant. REQUIRED unless
            indirectId is named (absent or blank is 400 PIX-0061). On a refund
            carrying indirectId it is DEPRECATED: an indirect keeps its
            customers in its own core, so the refunder is the original payee as
            the Pix recorded it. accountId is still accepted there, unchanged,
            when the direct participant's own credential sends the refund, and
            refused 400 PIX-0061 when an Access Manager partner is behind the
            request.
          examples:
            - 019a1b2c-3d4e-7f60-8a9b-0c1d2e3f4a5b
          type: string
        amount:
          description: Refund amount in centavos (must be greater than zero).
          examples:
            - 5000
          format: int64
          type: integer
        code:
          description: PIX return reason (BE08/FR01/MD06/SL02).
          examples:
            - MD06
          type: string
        description:
          description: Free-text refund description.
          examples:
            - Wrong amount
          type: string
        endToEndId:
          description: The original transaction's end-to-end id.
          examples:
            - E1234567890
          type: string
        indirectId:
          description: >-
            The registered indirect participant (UUID) that received the
            original Pix on its PIX position, required exactly then and debited
            for the refund: absent is 422 PIX-0135. Named, the original has to
            be held by that indirect, or the refund is refused 404 PIX-0147
            before anything is read, held or sent - another indirect's Pix, and
            a Pix received on a direct account, are not the named indirect's to
            return, and a token confined to one indirect has to name it here. It
            then passes the checks of a payment order's indirectId (422 PIX-0111
            feature off, 404 PIX-0095 unknown, 422 PIX-0100 not ACTIVE).
          examples:
            - 3f2504e0-4f89-41d3-9a0c-0305e82c3301
          format: uuid
          type: string
        payerIspb:
          description: >-
            The ISPB of the direct participant paying this refund back - the one
            that received the original Pix. OPTIONAL: omit it and the original
            is refunded by whichever participant holds it, exactly as before.
            Named, the original has to be booked in that participant's books, or
            the refund is refused 404 PIX-0147 before anything is read, held or
            sent - the same original named under another participant is not
            refunded. An ISPB this deployment does not act as is 422 PIX-0128.
            It is ROUTING DATA you supply, never a credential, and a token
            confined to one participant has to name it here; on a Pix received
            by an indirect, name the direct participant it rides alongside
            indirectId. Send it as an absent key, not an empty string.
          examples:
            - '12345678'
          pattern: ^[0-9A-Z]{8}$
          type: string
        transactionId:
          description: The original transaction id (UUID).
          examples:
            - d1f9c0a2-7b3e-4c51-9a6d-2f8e0b4c1a37
          type: string
      required:
        - endToEndId
        - transactionId
        - code
        - amount
      type: object
    RefundResponse:
      additionalProperties: false
      properties:
        accountId:
          description: >-
            The Midaz alias of the account the refund debits: the one the
            original credited, or the indirect's @pi_{ispb} on an indirect
            refund.
          examples:
            - '@recebedor'
          type: string
        amount:
          description: Refund amount in centavos.
          examples:
            - 5000
          format: int64
          type: integer
        code:
          description: The PIX return reason.
          examples:
            - MD06
          type: string
        description:
          description: Refund description.
          examples:
            - Wrong amount
          type: string
        endToEndId:
          description: The original transaction's end-to-end id.
          examples:
            - E1234567890
          type: string
        endToEndRefundId:
          description: >-
            The refund's own end-to-end id, filled when JD supplies it; may be
            empty while PENDING, which is not a failure.
          examples:
            - D1234567890
          type: string
        id:
          description: The created refund id.
          examples:
            - a2f9c0d1-...
          type: string
        status:
          description: >-
            eTransactionStatus name. A refund sent over SPI answers PENDING
            until SPI settles it.
          examples:
            - EXECUTED
          type: string
      required:
        - id
        - accountId
        - code
        - endToEndId
        - endToEndRefundId
        - amount
        - status
      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
    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.