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

# Process an inbound JDPI cash-in

> Registers an inbound PIX credit that JDPI has settled to this participant (JDPI section 9.3.2). JDPI calls it once per received credit, after settlement; it is idempotent on the end-to-end id (the mandatory Chave-Idempotencia header), so a redelivery of a credit already registered answers 409 PIX-0029 rather than posting the credit twice.

On success the credit is posted to the receiving customer's account and the response carries the three section 9.3.2 members: idReqJdPi, idCreditoSgct (the identifier of the credit entry this participant recorded) and dtHrCreditoSgct (when it was recorded). That response is an assertion that the money was booked; there is no field in it for a refusal.

NOT EVERY CREDIT LANDS ON A CUSTOMER ACCOUNT. This participant may also serve INDIRECT participants — other institutions that reach SPI through this participant's ISPB and are registered here with POST /v1/indirects. When recebedor.ispb names one of them and its registration is ACTIVE, the credit is posted to THAT institution's `@pi_{ispb}` settlement position instead of to a customer account. The destination is read from the registry row, never from the payload, and the recorded credit is stamped with the institution it belongs to. The 200 body is identical in both cases, so the response does not tell you which destination was used; that institution's own movements are read with GET /v1/indirects/{indirectId}/transactions.

An indirect credit also queues a NOTICE to the endpoint that registration carries (delivery.endpointUrl): one HTTPS POST forwarding this webhook's JD 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 (the send time in Unix seconds, not covered by the signature). The notice is enqueued in the same database transaction as the credit, but its delivery is AT-LEAST-ONCE and independent of this 200: the same notice can arrive more than once, and it can also fail permanently while the money stays booked. A receiving institution must dedup on endToEndId and must treat the movements feed, not the notice, as the record of truth.

Three ordering rules decide the destination and cannot be inferred from the payload:

- A pagador.ispb identifying Bacen (99999) short-circuits FIRST, ahead of any indirect matching, so it never reaches a settlement position either.
- A recebedor.ispb equal to this participant's OWN ISPB is always resolved against this participant's own customer records, never against the indirect registry.
- While this tenant's indirect-participants feature is switched OFF, recebedor.ispb is not matched against the registry at all and every credit is resolved against this participant's own customer records — so a credit addressed to a registered institution is answered 404 PIX-0115 rather than posted to its `@pi_{ispb}`. Register the institution AND enable the feature before pointing credits at it.

A credit that CANNOT be registered is therefore answered with an HTTP error, never with a 200. Each carries a distinct code in the problem body's `code` member:

- 404 PIX-0115 - the receiving account named by the credit was not found here. Check recebedor.nrAgencia/recebedor.nrConta, or recebedor.cpfCnpj when no account coordinates are sent.
- 404 PIX-0119 - recebedor.ispb is neither this participant's own ISPB nor an ACTIVE indirect participant registered in this tenant. It covers both a receiver with no registration at all and one whose registration is not ACTIVE (suspended, closed, or a legacy row that never finished being set up); the two are deliberately not distinguished on the wire, because neither is something the sender can act on differently.
- 409 PIX-0116 - recebedor.cpfCnpj names more than one account here, so the destination is undeterminable. Address the credit to specific account coordinates.
- 409 PIX-0117 - the account addressed by recebedor.nrAgencia/recebedor.nrConta belongs to a different holder than recebedor.cpfCnpj names.
- 409 PIX-0118 - the addressed account exists here but is not set up to receive credits.
- 409 PIX-0029 - this end-to-end id was already registered as a credit here. The redelivery posted nothing; the original credit stands.
- 500 PIX-0120 - a provisioning fault at this participant, not a problem with the request. The credit is safe to redeliver once it is corrected.

WHICH OF THOSE AN INDIRECT CREDIT CAN ACTUALLY HIT is a shorter list, because its destination comes from the registry rather than from a customer lookup. PIX-0119 is the one: it is what a receiver ISPB with no ACTIVE registration answers. PIX-0115, PIX-0116, PIX-0117, PIX-0118 and PIX-0120 are all decided by the own-customer lookup and are unreachable once recebedor.ispb resolves to an ACTIVE registration — so seeing any of them means the credit was NOT treated as an indirect one. PIX-0029 behaves identically on both paths. A registry read that fails is a 500 like any other dependency failure: nothing is registered, and the credit is safe to redeliver.

One outcome acknowledges 200 WITHOUT posting a credit: a pagador.ispb identifying Bacen (99999), which this participant nulls by design. Its response carries the acknowledgement echo (idReqSistemaCliente, idReqJdPi, endToEndIdOriginal, endToEndIdDevolucao) and no idCreditoSgct.

Malformed payloads are rejected with 400 at the edge, before any resolution runs: 400 PIX-0061 for a body that fails schema validation, and 400 PIX-0061 for a missing endToEndId, a valor that is not a positive finite amount, or a malformed CPF/CNPJ or ISPB on either participant block.



## OpenAPI

````yaml /en/openapi/v3-current/pix.yaml post /v1/webhooks/cash-ins
openapi: 3.1.0
info:
  description: Brazilian PIX Direct (DICT + SPI) plugin API.
  title: plugin-br-pix-jd
  version: 1.0.0
servers: []
security:
  - BearerAuth: []
paths:
  /v1/webhooks/cash-ins:
    post:
      tags:
        - Webhooks
      summary: Process an inbound JDPI cash-in
      description: >-
        Registers an inbound PIX credit that JDPI has settled to this
        participant (JDPI section 9.3.2). JDPI calls it once per received
        credit, after settlement; it is idempotent on the end-to-end id (the
        mandatory Chave-Idempotencia header), so a redelivery of a credit
        already registered answers 409 PIX-0029 rather than posting the credit
        twice.


        On success the credit is posted to the receiving customer's account and
        the response carries the three section 9.3.2 members: idReqJdPi,
        idCreditoSgct (the identifier of the credit entry this participant
        recorded) and dtHrCreditoSgct (when it was recorded). That response is
        an assertion that the money was booked; there is no field in it for a
        refusal.


        NOT EVERY CREDIT LANDS ON A CUSTOMER ACCOUNT. This participant may also
        serve INDIRECT participants — other institutions that reach SPI through
        this participant's ISPB and are registered here with POST /v1/indirects.
        When recebedor.ispb names one of them and its registration is ACTIVE,
        the credit is posted to THAT institution's `@pi_{ispb}` settlement
        position instead of to a customer account. The destination is read from
        the registry row, never from the payload, and the recorded credit is
        stamped with the institution it belongs to. The 200 body is identical in
        both cases, so the response does not tell you which destination was
        used; that institution's own movements are read with GET
        /v1/indirects/{indirectId}/transactions.


        An indirect credit also queues a NOTICE to the endpoint that
        registration carries (delivery.endpointUrl): one HTTPS POST forwarding
        this webhook's JD 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 (the send time in
        Unix seconds, not covered by the signature). The notice is enqueued in
        the same database transaction as the credit, but its delivery is
        AT-LEAST-ONCE and independent of this 200: the same notice can arrive
        more than once, and it can also fail permanently while the money stays
        booked. A receiving institution must dedup on endToEndId and must treat
        the movements feed, not the notice, as the record of truth.


        Three ordering rules decide the destination and cannot be inferred from
        the payload:


        - A pagador.ispb identifying Bacen (99999) short-circuits FIRST, ahead
        of any indirect matching, so it never reaches a settlement position
        either.

        - A recebedor.ispb equal to this participant's OWN ISPB is always
        resolved against this participant's own customer records, never against
        the indirect registry.

        - While this tenant's indirect-participants feature is switched OFF,
        recebedor.ispb is not matched against the registry at all and every
        credit is resolved against this participant's own customer records — so
        a credit addressed to a registered institution is answered 404 PIX-0115
        rather than posted to its `@pi_{ispb}`. Register the institution AND
        enable the feature before pointing credits at it.


        A credit that CANNOT be registered is therefore answered with an HTTP
        error, never with a 200. Each carries a distinct code in the problem
        body's `code` member:


        - 404 PIX-0115 - the receiving account named by the credit was not found
        here. Check recebedor.nrAgencia/recebedor.nrConta, or recebedor.cpfCnpj
        when no account coordinates are sent.

        - 404 PIX-0119 - recebedor.ispb is neither this participant's own ISPB
        nor an ACTIVE indirect participant registered in this tenant. It covers
        both a receiver with no registration at all and one whose registration
        is not ACTIVE (suspended, closed, or a legacy row that never finished
        being set up); the two are deliberately not distinguished on the wire,
        because neither is something the sender can act on differently.

        - 409 PIX-0116 - recebedor.cpfCnpj names more than one account here, so
        the destination is undeterminable. Address the credit to specific
        account coordinates.

        - 409 PIX-0117 - the account addressed by
        recebedor.nrAgencia/recebedor.nrConta belongs to a different holder than
        recebedor.cpfCnpj names.

        - 409 PIX-0118 - the addressed account exists here but is not set up to
        receive credits.

        - 409 PIX-0029 - this end-to-end id was already registered as a credit
        here. The redelivery posted nothing; the original credit stands.

        - 500 PIX-0120 - a provisioning fault at this participant, not a problem
        with the request. The credit is safe to redeliver once it is corrected.


        WHICH OF THOSE AN INDIRECT CREDIT CAN ACTUALLY HIT is a shorter list,
        because its destination comes from the registry rather than from a
        customer lookup. PIX-0119 is the one: it is what a receiver ISPB with no
        ACTIVE registration answers. PIX-0115, PIX-0116, PIX-0117, PIX-0118 and
        PIX-0120 are all decided by the own-customer lookup and are unreachable
        once recebedor.ispb resolves to an ACTIVE registration — so seeing any
        of them means the credit was NOT treated as an indirect one. PIX-0029
        behaves identically on both paths. A registry read that fails is a 500
        like any other dependency failure: nothing is registered, and the credit
        is safe to redeliver.


        One outcome acknowledges 200 WITHOUT posting a credit: a pagador.ispb
        identifying Bacen (99999), which this participant nulls by design. Its
        response carries the acknowledgement echo (idReqSistemaCliente,
        idReqJdPi, endToEndIdOriginal, endToEndIdDevolucao) and no
        idCreditoSgct.


        Malformed payloads are rejected with 400 at the edge, before any
        resolution runs: 400 PIX-0061 for a body that fails schema validation,
        and 400 PIX-0061 for a missing endToEndId, a valor that is not a
        positive finite amount, or a malformed CPF/CNPJ or ISPB on either
        participant block.
      operationId: createWebhookCashIn
      parameters:
        - description: >-
            Idempotency key (= the endToEndId of the transaction). Mandatory per
            section 9.3.2.
          in: header
          name: Chave-Idempotencia
          required: true
          schema:
            description: >-
              Idempotency key (= the endToEndId of the transaction). Mandatory
              per section 9.3.2.
            examples:
              - E0435879820200123221500000000001
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CashInBody'
        required: true
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CashInResponse'
          description: OK
        '400':
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Detail'
          description: Bad Request
        '404':
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Detail'
          description: Not Found
        '409':
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Detail'
          description: Conflict
        '500':
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Detail'
          description: Internal Server Error
components:
  schemas:
    CashInBody:
      additionalProperties: true
      properties:
        chave:
          description: The PIX key (present for key-initiated cash-ins).
          examples:
            - recipient@bank.com
          type: string
        cnpjIniciadorPagamento:
          description: Payment initiator CNPJ (a v5.5.0 string).
          examples:
            - '11144477735'
          type: string
        dtContabil:
          description: Accounting date (optional).
          examples:
            - '2026-06-20'
          type: string
        dtHrLiquidacao:
          description: Settlement timestamp (optional).
          examples:
            - '2026-06-20T10:00:01Z'
          type: string
        dtHrOp:
          description: Operation timestamp (ISO-8601).
          examples:
            - '2026-06-20T10:00:00Z'
          type: string
        endToEndId:
          description: SPI end-to-end id (idempotency + dedup key).
          examples:
            - E2E-1
          type: string
        finalidade:
          description: Finality (eFinality).
          examples:
            - 0
          format: int64
          type: integer
        idConciliacaoRecebedor:
          description: Recipient conciliation id (stamped on the row + the 24h marker).
          examples:
            - CONC-1
          type: string
        idReqJdPi:
          description: JDPI request id (becomes the local row id when a UUID).
          examples:
            - JDPI-1
          type: string
        infEntreClientes:
          description: Free-text inter-client info.
          examples:
            - note
          type: string
        ispbPss:
          description: Saque/troco PSS participant ISPB (a v5.5.0 string).
          examples:
            - '12345678'
          type: string
        modalidadeAgente:
          description: Agent modality (eModalityAgent).
          examples:
            - 0
          format: int64
          type: integer
        pagador:
          $ref: '#/components/schemas/PayerBlock'
          description: The payer participant block.
        prioridadePagamento:
          description: Payment priority (ePaymentPriority).
          examples:
            - 0
          format: int64
          type: integer
        recebedor:
          $ref: '#/components/schemas/PayeeBlock'
          description: The receiver participant block (the credit account source).
        tpIniciacao:
          description: >-
            Payment initiation mechanism (section 9.3.2): 0 manual, 1 chave, 2
            QR Code estatico, 3 QR Code dinamico, 6 ITP, 8 Pix Automatico, 9/10
            Pix por aproximacao. Both QR values (2 and 3) book the credit on the
            QR route pair; every other value books on the key route pair.
          examples:
            - 0
          format: int64
          type: integer
        tpPrioridadePagamento:
          description: Payment priority type.
          examples:
            - 0
          format: int64
          type: integer
        valor:
          description: Amount in reais (a JSON number).
          examples:
            - 100.5
          format: double
          type: number
        vlrDetalhe:
          description: Optional value-detail entries.
          items:
            $ref: '#/components/schemas/ValueDetailBlock'
          type:
            - array
            - 'null'
      required:
        - idReqJdPi
        - endToEndId
        - tpIniciacao
        - pagador
        - recebedor
        - dtHrOp
        - valor
      type: object
    CashInResponse:
      additionalProperties: false
      properties:
        dtHrCreditoSgct:
          description: SGCT credit timestamp (ISO-8601), on a credited result.
          examples:
            - '2026-06-20T10:00:01Z'
          type: string
        dtHrReqJdPi:
          description: Request timestamp (ISO-8601).
          examples:
            - '2026-06-20T10:00:00Z'
          type: string
        endToEndIdDevolucao:
          description: Echoed return end-to-end id.
          examples:
            - E2E-1
          type: string
        endToEndIdOriginal:
          description: Echoed original end-to-end id.
          examples:
            - E2E-1
          type: string
        idCreditoSgct:
          description: SGCT credit lançamento id (GUID), on a credited result.
          examples:
            - SGCT-1
          type: string
        idReqJdPi:
          description: Echoed JDPI request id.
          examples:
            - JDPI-1
          type: string
        idReqSistemaCliente:
          description: Echoed client-system request id.
          examples:
            - JDPI-1
          type: string
      type: object
    Detail:
      additionalProperties: false
      properties:
        code:
          description: >-
            Stable, machine-readable domain error code scoped to the emitting
            service (format: <SERVICE>-NNNN).
          examples:
            - ERR-0001
          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
    PayerBlock:
      additionalProperties: true
      properties:
        cpfCnpj:
          description: Payer document CPF/CNPJ (a v5.5.0 string).
          examples:
            - '11144477735'
          type: string
        ispb:
          description: Payer participant ISPB (a v5.5.0 string).
          examples:
            - '12345678'
          type: string
        nome:
          description: Payer name (Obrg=Sim on the pagador block).
          examples:
            - Jane Doe
          type: string
        nrAgencia:
          description: Agency/branch number (the participant branch source; Obrg=Nao).
          examples:
            - '0001'
          type: string
        nrConta:
          description: Account number (NEVER used as the branch).
          examples:
            - '1234567'
          type: string
        tpConta:
          description: >-
            Account type (eAccountType: 0=checking). §9.3.2 Obrg=Sim, but no
            code reads it, so it is tolerated-absent.
          examples:
            - 0
          format: int64
          type: integer
        tpPessoa:
          description: >-
            Person type (ePersonType: 0=natural, 1=legal). §9.3.2 Obrg=Sim, but
            no code reads it, so it is tolerated-absent.
          examples:
            - 0
          format: int64
          type: integer
      required:
        - ispb
        - cpfCnpj
        - nome
        - nrConta
      type: object
    PayeeBlock:
      additionalProperties: true
      properties:
        cpfCnpj:
          description: Receiver document CPF/CNPJ (a v5.5.0 string).
          examples:
            - '11144477735'
          type: string
        ispb:
          description: Receiver participant ISPB (a v5.5.0 string).
          examples:
            - '12345678'
          type: string
        nrAgencia:
          description: Agency/branch number (the participant branch source; Obrg=Nao).
          examples:
            - '0001'
          type: string
        nrConta:
          description: Account number (NEVER used as the branch).
          examples:
            - '1234567'
          type: string
        tpConta:
          description: >-
            Account type (eAccountType: 0=checking). §9.3.2 Obrg=Sim, but no
            code reads it, so it is tolerated-absent.
          examples:
            - 0
          format: int64
          type: integer
        tpPessoa:
          description: >-
            Person type (ePersonType: 0=natural, 1=legal). §9.3.2 Obrg=Sim, but
            no code reads it, so it is tolerated-absent.
          examples:
            - 0
          format: int64
          type: integer
      required:
        - ispb
        - cpfCnpj
        - nrConta
      type: object
    ValueDetailBlock:
      additionalProperties: true
      properties:
        tipo:
          description: Value-detail type.
          examples:
            - 0
          format: int64
          type: integer
        vlrTarifaDinheiroCompra:
          description: Cash-purchase fee amount (reais).
          examples:
            - 0
          format: double
          type: number
      required:
        - vlrTarifaDinheiroCompra
        - tipo
      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

````