> ## 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 a Transfer

> Use this endpoint to confirm and execute a previously initiated transfer. The system validates the initiationId, checks the sender's balance, holds funds in Midaz, and routes the transfer to JD SPB (for TED OUT) or creates an internal Midaz transaction (for P2P). Submitting the same initiationId returns the same transferId.



## OpenAPI

````yaml en/openapi/v3-current/ted.yaml post /v1/transfers/process
openapi: 3.0.3
info:
  title: Bank Transfer (TED) Plugin API
  description: >-
    Complete API for Brazilian bank transfers (TED OUT, TED IN, P2P) through the
    Lerian platform, including transfer initiation, processing, status tracking,
    and cancellation.
  version: 1.1.9
servers:
  - url: https://ted.sandbox.lerian.net
    description: Sandbox (placeholder — not yet available for public access)
security:
  - BearerAuth: []
  - OAuth2ClientCredentials:
      - api
  - OAuth2Password:
      - api
tags:
  - name: Transfers API
    description: Endpoints for initiating, processing, tracking, and cancelling transfers.
  - name: Webhooks
    description: >-
      Endpoints for registering and managing tenant-scoped webhook subscriptions
      for transfer events.
  - name: Webhook DLQ
    description: Endpoints for inspecting and retrying webhook dead-letter queue messages.
paths:
  /v1/transfers/process:
    post:
      tags:
        - Transfers API
      summary: Process a Transfer
      description: >-
        Use this endpoint to confirm and execute a previously initiated
        transfer. The system validates the initiationId, checks the sender's
        balance, holds funds in Midaz, and routes the transfer to JD SPB (for
        TED OUT) or creates an internal Midaz transaction (for P2P). Submitting
        the same initiationId returns the same transferId.
      operationId: processTransfer
      parameters:
        - $ref: '#/components/parameters/XOrganizationId'
        - $ref: '#/components/parameters/XIdempotencyKey'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ProcessTransferRequest'
            examples:
              process:
                summary: Process initiated transfer
                value:
                  initiationId: 019c96a0-aa10-7abc-d1e2-8c9d0e1f2a3b
      responses:
        '200':
          description: >-
            Indicates that the transfer was confirmed and processing has
            started.


            Repeated calls with the same `X-Idempotency` key replay the cached
            response.


            See [Retries and idempotency](/en/reference/retries-idempotency) for
            more details.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProcessTransferResponse'
              examples:
                success:
                  summary: Transfer processing
                  value:
                    transferId: 019c96a0-ab10-7cde-f1a2-0e1f2a3b4c5d
                    confirmationNumber: '20260201001'
                    status: PROCESSING
                    feeAmount: 1.5
                    totalAmount: 1002
        '202':
          description: >-
            Indicates that the TED OUT advance failed but the transfer was
            escalated to the reconciliation worker. The Midaz hold is intact.
            Poll `GET /v1/transfers/{transferId}` for the terminal status. The
            body is an error envelope, not a transfer response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                escalated:
                  summary: Escalated to reconciliation
                  value:
                    error:
                      code: BTF-9010
                      service: plugin
                      category: transient
                      message: >-
                        TED_OUT advance failed but transfer was escalated to the
                        reconciliation worker; hold is intact — poll the
                        transfer status for the terminal result
                      requestId: 6d3e2a68-1f2b-4c3d-9e4f-5a6b7c8d9e0f
                      fields:
                        hint: >-
                          GET /v1/transfers/{transferId} will converge to the
                          final status
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/InitiationNotFound'
        '409':
          $ref: '#/components/responses/AlreadyProcessed'
        '410':
          $ref: '#/components/responses/InitiationExpired'
        '422':
          $ref: '#/components/responses/LimitExceeded'
        '429':
          $ref: '#/components/responses/RateLimitExceeded'
        '500':
          $ref: '#/components/responses/InternalServerError'
        '502':
          $ref: '#/components/responses/BadGateway'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
components:
  parameters:
    XOrganizationId:
      name: X-Organization-Id
      in: header
      required: true
      description: >-
        Midaz organization scope for the request, used for downstream CRM, Fees,
        and Midaz calls. Required on org-scoped transfer routes in every
        deployment mode; a missing or non-UUID value returns 400. This is not
        the tenant identifier — tenantId is derived from the bearer JWT or
        authenticated context, never from this header. Background workers (TED
        IN poller, reconciliation) have no request header and, in single-tenant
        mode, fall back to the deployment's `ORGANIZATION_ID` env.
      schema:
        type: string
        format: uuid
      example: 019c96a0-0a98-7287-9a31-786e0809c769
    XIdempotencyKey:
      name: X-Idempotency
      in: header
      required: true
      description: >-
        Required idempotency key for safe retries. Use a UUID v4 or unique
        business identifier. If the same key is sent again and the original
        request was already processed, the cached response is returned.


        See [Retries and idempotency](/en/reference/retries-idempotency) for
        details.
      schema:
        type: string
        maxLength: 255
      example: 019c96a0-aa10-7abc-d1e2-8c9d0e1f2a3b
  schemas:
    ProcessTransferRequest:
      type: object
      oneOf:
        - required:
            - initiationId
          not:
            anyOf:
              - required:
                  - signingArtifactId
              - required:
                  - payloadHash
              - required:
                  - signature
        - required:
            - initiationId
            - signingArtifactId
            - payloadHash
            - signature
      properties:
        initiationId:
          type: string
          format: uuid
          description: >-
            The initiation ID returned by the Initiate Transfer endpoint.
            Expires after 24 hours.
          example: 019c96a0-aa10-7abc-d1e2-8c9d0e1f2a3b
        signingArtifactId:
          type: string
          format: uuid
          description: >-
            Identifier of the frozen signing artifact returned by Prepare
            Transfer Signature.
          example: 019c96a0-bb10-7def-a1b2-3c4d5e6f7a8b
        payloadHash:
          type: string
          description: SHA-256 hash of the canonical payload that was signed.
          example: 8f0c7f5c1c7b4d9f2f5c7d1a0d4c9a2b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f
        signature:
          type: string
          description: Base64-encoded signature for tenants that sign outside the plugin.
          example: base64-signature-here
    ProcessTransferResponse:
      type: object
      required:
        - transferId
        - confirmationNumber
        - status
        - feeAmount
        - totalAmount
      properties:
        transferId:
          type: string
          format: uuid
          description: The unique transfer ID. Use this value to track the transfer status.
          example: 019c96a0-ab10-7cde-f1a2-0e1f2a3b4c5d
        confirmationNumber:
          type: string
          maxLength: 20
          description: >-
            A human-readable confirmation number. Format is YYYYMMDD followed by
            a short hex suffix derived from the transfer ID (e.g.
            20260201aa10bc3d4e5f).
          example: '20260201001'
        status:
          allOf:
            - $ref: '#/components/schemas/TransferStatus'
          description: >-
            The current transfer status. For TED_OUT transfers, the status
            immediately after processing is always PROCESSING.
        feeAmount:
          type: number
          format: decimal
          description: The fee amount as calculated during initiation.
          example: 1.5
        totalAmount:
          type: number
          format: decimal
          description: The total amount held or transferred, including the fee.
          example: 1002
        packageAppliedId:
          type: string
          format: uuid
          nullable: true
          description: ID of the fee package applied to this transfer, if any.
          example: 019c96a0-ad10-7fab-c1d2-3b4c5d6e7f8a
    ErrorResponse:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - service
            - category
            - message
            - requestId
          properties:
            code:
              type: string
              description: >-
                The stable error code. Plugin errors use the `BTF-XXXX` format;
                JD SPB business/auth rejections pass through the raw vendor code
                verbatim (e.g. `AAC90`, `ACE95`, `DVE01`), and transport-level
                JD failures surface the synthetic markers `TRANSPORT` or
                `JD_MISSING_CODE`. Match on this value rather than on the HTTP
                status.
              example: BTF-0010
            service:
              type: string
              description: The service or domain that produced the error.
              example: plugin
            category:
              type: string
              description: Machine-readable error category used for retry decisions.
              enum:
                - deterministic
                - transient
                - rate_limit
                - plugin
              example: deterministic
            message:
              type: string
              description: A human-readable error summary.
              example: >-
                Transfers can only be initiated Monday-Friday between 06:30 and
                17:00 Brasília time
            requestId:
              type: string
              description: The request correlation ID. Present even when empty.
              example: 6d3e2a68-1f2b-4c3d-9e4f-5a6b7c8d9e0f
            fields:
              type: object
              additionalProperties: true
              description: >-
                Structured validation or retry metadata when available.
                Field-level, header, path, and query validation details are all
                returned here.
              example:
                currentTime: '2026-02-01T18:30:00-03:00'
                operatingHours: Mon-Fri 06:30-17:00 UTC-3
    TransferStatus:
      type: string
      enum:
        - CREATED
        - PENDING
        - PROCESSING
        - COMPLETED
        - REJECTED
        - FAILED
        - CANCELLED
        - RECEIVED
      description: >-
        The current status of the transfer. For TED OUT: CREATED → PENDING →
        PROCESSING → COMPLETED, REJECTED, or FAILED. For P2P: CREATED →
        PROCESSING → COMPLETED or FAILED (PENDING is an SPB-specific state and
        does not apply to P2P). Transfers can be CANCELLED while in CREATED or
        PENDING status. For TED IN: RECEIVED → PROCESSING → COMPLETED or FAILED.
        A COMPLETED TED IN can also transition to FAILED in the event of a
        chargeback.
      example: COMPLETED
  responses:
    BadRequest:
      description: >-
        Indicates that the request contains invalid input. Check the field
        details for specific validation errors.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            invalidInput:
              summary: Validation error
              value:
                error:
                  code: BTF-0001
                  service: plugin
                  category: deterministic
                  message: >-
                    The request contains invalid fields. Check the field details
                    below.
                  requestId: 6d3e2a68-1f2b-4c3d-9e4f-5a6b7c8d9e0f
                  fields:
                    recipientIspb: must be 8 digits
                    amount: must be positive
    Unauthorized:
      description: Indicates that the request is missing a valid authentication token.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            unauthorized:
              summary: Missing authorization
              value:
                error:
                  code: BTF-0401
                  service: plugin
                  category: deterministic
                  message: Missing or invalid authentication token
                  requestId: 6d3e2a68-1f2b-4c3d-9e4f-5a6b7c8d9e0f
    Forbidden:
      description: >-
        Indicates that the caller is authenticated but lacks permission for this
        operation, or the tenant is not licensed for this endpoint.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            notLicensed:
              summary: Tenant not licensed
              value:
                error:
                  code: BTF-0403
                  service: plugin
                  category: deterministic
                  message: Tenant is not licensed to use this endpoint
                  requestId: 6d3e2a68-1f2b-4c3d-9e4f-5a6b7c8d9e0f
            permissionDenied:
              summary: Caller lacks permission
              value:
                error:
                  code: BTF-0405
                  service: plugin
                  category: deterministic
                  message: Caller lacks permission for this resource
                  requestId: 6d3e2a68-1f2b-4c3d-9e4f-5a6b7c8d9e0f
    InitiationNotFound:
      description: >-
        Indicates that the initiation was not found or belongs to a different
        organization.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            initiationNotFound:
              summary: Invalid initiation ID
              value:
                error:
                  code: BTF-0201
                  service: plugin
                  category: deterministic
                  message: Initiation not found or belongs to different organization
                  requestId: 6d3e2a68-1f2b-4c3d-9e4f-5a6b7c8d9e0f
    AlreadyProcessed:
      description: >-
        Indicates that this initiation has already been processed into a
        transfer.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            alreadyProcessed:
              summary: Initiation used
              value:
                error:
                  code: BTF-0203
                  service: plugin
                  category: deterministic
                  message: This initiation has already been processed
                  requestId: 6d3e2a68-1f2b-4c3d-9e4f-5a6b7c8d9e0f
                  fields:
                    transferId: 019c96a0-ab10-7cde-f1a2-0e1f2a3b4c5d
    InitiationExpired:
      description: >-
        Indicates that the initiation has expired after 24 hours. A new
        initiation must be created.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            expired:
              summary: Initiation too old
              value:
                error:
                  code: BTF-0202
                  service: plugin
                  category: deterministic
                  message: Initiation expired after 24 hours. Create a new initiation.
                  requestId: 6d3e2a68-1f2b-4c3d-9e4f-5a6b7c8d9e0f
                  fields:
                    expiresAt: '2026-01-31T15:30:00-03:00'
    LimitExceeded:
      description: Indicates that the transfer amount exceeds the configured usage limit.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            limitExceeded:
              summary: Daily limit reached
              value:
                error:
                  code: BTF-0011
                  service: plugin
                  category: deterministic
                  message: Transfer amount exceeds daily limit
                  requestId: 6d3e2a68-1f2b-4c3d-9e4f-5a6b7c8d9e0f
                  fields:
                    limitType: PERIOD
                    periodType: DAILY
                    limitAmount: 10000
                    usedAmount: 8000
                    requestedAmount: 3000
                    excessAmount: 1000
    RateLimitExceeded:
      description: >-
        Indicates that the rate limit has been exceeded. Retry after the number
        of seconds specified in the Retry-After header.
      headers:
        Retry-After:
          description: Seconds until rate limit resets
          schema:
            type: integer
            example: 60
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            rateLimitExceeded:
              summary: Too many requests
              value:
                error:
                  code: BTF-0429
                  service: plugin
                  category: rate_limit
                  message: >-
                    Too many requests. Retry after the interval indicated by the
                    `Retry-After` header.
                  requestId: 6d3e2a68-1f2b-4c3d-9e4f-5a6b7c8d9e0f
              description: >
                Rate-limit responses use the dedicated `BTF-0429` code with the
                `rate_limit` category. Clients should back off using the HTTP
                status `429` and the `Retry-After` header.
    InternalServerError:
      description: Indicates that an unexpected internal error occurred.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            internalError:
              summary: Internal error
              value:
                error:
                  code: BTF-9000
                  service: plugin
                  category: plugin
                  message: Unexpected error while processing the request
                  requestId: 6d3e2a68-1f2b-4c3d-9e4f-5a6b7c8d9e0f
    BadGateway:
      description: >-
        Indicates that JD SPB rejected the request at the authentication or
        configuration layer (signing certificate, credentials, or
        configuration). The raw JD vendor code (AAC*, AAE*) passes through
        verbatim on the `code` field.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            jdAuthRejected:
              summary: JD SPB auth rejection
              value:
                error:
                  code: AAC90
                  service: jd_spb
                  category: deterministic
                  message: JD SPB rejected the signing certificate or credentials
                  requestId: 6d3e2a68-1f2b-4c3d-9e4f-5a6b7c8d9e0f
    ServiceUnavailable:
      description: >-
        Indicates that an external service (CRM, JD SPB, Midaz, or Fees) is
        temporarily unavailable.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            crmUnavailable:
              summary: CRM service down
              value:
                error:
                  code: BTF-0502
                  service: crm
                  category: transient
                  message: >-
                    Unable to validate account. The CRM service is temporarily
                    unavailable. Try again later.
                  requestId: 6d3e2a68-1f2b-4c3d-9e4f-5a6b7c8d9e0f
            jdUnavailable:
              summary: JD SPB unavailable
              value:
                error:
                  code: TRANSPORT
                  service: jd_spb
                  category: transient
                  message: >-
                    Unable to submit transfer. The JD SPB service is temporarily
                    unavailable. Try again later.
                  requestId: 6d3e2a68-1f2b-4c3d-9e4f-5a6b7c8d9e0f
            midazUnavailable:
              summary: Midaz ledger unavailable
              value:
                error:
                  code: BTF-2000
                  service: midaz
                  category: transient
                  message: >-
                    Unable to process transfer. The Midaz ledger service is
                    temporarily unavailable. Try again later.
                  requestId: 6d3e2a68-1f2b-4c3d-9e4f-5a6b7c8d9e0f
            feeServiceUnavailable:
              summary: Fee service unavailable (fail-closed mode)
              value:
                error:
                  code: BTF-3000
                  service: fees
                  category: transient
                  message: >-
                    Unable to calculate fee. The fee service is temporarily
                    unavailable. Try again later.
                  requestId: 6d3e2a68-1f2b-4c3d-9e4f-5a6b7c8d9e0f
            dlqInspectorUnavailable:
              summary: DLQ inspector not configured
              value:
                error:
                  code: BTF-9005
                  service: plugin
                  category: deterministic
                  message: DLQ inspector is not configured
                  requestId: 6d3e2a68-1f2b-4c3d-9e4f-5a6b7c8d9e0f
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: >-
        JWT Bearer token authentication. The tenantId is derived from the bearer
        token or authenticated request context and is not supplied through
        X-Organization-Id.
    OAuth2ClientCredentials:
      type: oauth2
      flows:
        clientCredentials:
          tokenUrl: /v1/login/oauth/access_token
          scopes:
            api: TED transfer API access
    OAuth2Password:
      type: oauth2
      flows:
        password:
          tokenUrl: /v1/login/oauth/access_token
          scopes:
            api: TED transfer API access

````