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

# Initiate a Transfer

> Use this endpoint to initiate a transfer by validating sender data, checking operating hours and usage limits, detecting duplicates, and calculating the fee. No funds are held at this step. The returned initiationId is valid for 24 hours and must be confirmed via the Process Transfer endpoint. Use the `X-Idempotency` header for guaranteed deduplication.



## OpenAPI

````yaml en/openapi/v3-current/ted.yaml post /v1/transfers/initiate
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/initiate:
    post:
      tags:
        - Transfers API
      summary: Initiate a Transfer
      description: >-
        Use this endpoint to initiate a transfer by validating sender data,
        checking operating hours and usage limits, detecting duplicates, and
        calculating the fee. No funds are held at this step. The returned
        initiationId is valid for 24 hours and must be confirmed via the Process
        Transfer endpoint. Use the `X-Idempotency` header for guaranteed
        deduplication.
      operationId: initiateTransfer
      parameters:
        - $ref: '#/components/parameters/XOrganizationId'
        - $ref: '#/components/parameters/XIdempotencyKey'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/InitiateTransferRequest'
            examples:
              tedOut:
                summary: TED OUT to external bank
                value:
                  senderAccountId: 019c96a0-0c0c-7221-8cf3-13313fb60081
                  recipient:
                    ispb: '00000000'
                    branch: '0001'
                    account: '1234567890'
                    accountType: CACC
                    holderName: João Silva
                    holderDocument: '12345678901'
                  amount: 1000.5
                  description: Payment for services
                  metadata:
                    invoiceId: INV-2024-001
              p2p:
                summary: P2P (same institution)
                value:
                  senderAccountId: 019c96a0-0c0c-7221-8cf3-13313fb60081
                  recipient:
                    ispb: '12345678'
                    branch: '0001'
                    account: '9876543210'
                    accountType: CACC
                    holderName: Maria Santos
                    holderDocument: '98765432100'
                  amount: 500
                  description: Transfer to friend
      responses:
        '200':
          description: >-
            Indicates that the transfer was initiated successfully and is
            awaiting confirmation.


            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/InitiateTransferResponse'
              examples:
                success:
                  summary: Initiation with fee
                  value:
                    initiationId: 019c96a0-aa10-7abc-d1e2-8c9d0e1f2a3b
                    feeAmount: 1.5
                    totalAmount: 1002
                    estimatedCompletionAt: '2026-02-01T18:00:00-03:00'
                    expiresAt: '2026-02-02T15:30:00-03:00'
                    status: PENDING_CONFIRMATION
                freeTransfer:
                  summary: No fee configured
                  value:
                    initiationId: 019c96a0-aa20-7bcd-e1f2-9d0e1f2a3b4c
                    feeAmount: 0
                    totalAmount: 1000.5
                    estimatedCompletionAt: '2026-02-01T18:00:00-03:00'
                    expiresAt: '2026-02-02T15:30:00-03:00'
                    status: PENDING_CONFIRMATION
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/AccountNotFound'
        '409':
          $ref: '#/components/responses/DuplicateTransfer'
        '422':
          $ref: '#/components/responses/OperatingHoursViolation'
        '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:
    InitiateTransferRequest:
      type: object
      required:
        - senderAccountId
        - recipient
        - amount
        - purpose
      properties:
        senderAccountId:
          type: string
          format: uuid
          description: The Midaz account ID of the sender.
          example: 019c96a0-0c0c-7221-8cf3-13313fb60081
        recipient:
          $ref: '#/components/schemas/RecipientDetails'
        amount:
          type: number
          format: decimal
          minimum: 0.01
          maximum: 999999.99
          description: The transfer amount in BRL.
          example: 1000.5
        purpose:
          type: string
          pattern: ^[0-9]{1,4}$
          maxLength: 4
          description: >
            BACEN SPB FinlddCli code identifying the transfer purpose. Must be
            1–4 ASCII digits.


            Common FinlddCli codes:
              * `1` — Pagamento de Impostos, Tributos e Taxas
              * `3` — Pagamentos de Dividendos
              * `10` — Crédito em Conta
              * `100` — Depósito Judicial

            Refer to the BACEN _Dicionário de Domínios_ (`FinlddCli`) for the
            full table of active codes.


            **Note:** the plugin currently accepts FinlddCli values of up to 4
            digits. 5-digit codes from the BACEN catalog (such as `99999` —
            _Outros_) are not yet supported and will return a validation error.
          example: '10'
        description:
          type: string
          maxLength: 140
          description: A free-text description of the transfer.
          example: Payment for services
        metadata:
          type: object
          additionalProperties: true
          description: Custom metadata as key-value pairs.
          example:
            invoiceId: INV-2024-001
            orderId: ORD-2024-123
    InitiateTransferResponse:
      type: object
      required:
        - initiationId
        - feeAmount
        - totalAmount
        - estimatedCompletionAt
        - expiresAt
        - status
      properties:
        initiationId:
          type: string
          format: uuid
          description: >-
            The unique initiation ID. Use this value in the Process Transfer
            endpoint to confirm the transfer.
          example: 019c96a0-aa10-7abc-d1e2-8c9d0e1f2a3b
        feeAmount:
          type: number
          format: decimal
          description: >-
            The calculated fee amount. Returns 0.00 if fees are disabled for
            this organization.
          example: 1.5
        totalAmount:
          type: number
          format: decimal
          description: The total amount, calculated as the transfer amount plus the fee.
          example: 1002
        estimatedCompletionAt:
          type: string
          format: date-time
          description: The estimated time when the transfer will be completed.
          example: '2026-02-01T18:00:00-03:00'
        expiresAt:
          type: string
          format: date-time
          description: The time when this initiation expires, 24 hours after creation.
          example: '2026-02-02T15:30:00-03:00'
        status:
          $ref: '#/components/schemas/InitiationStatus'
        feeEntries:
          type: array
          description: >-
            Itemized fee breakdown. Each entry corresponds to one fee charged
            during the transfer.
          items:
            type: object
            properties:
              label:
                type: string
                description: Fee identifier label.
                example: ted_transfer_fee
              amount:
                type: number
                format: decimal
                description: Fee amount.
                example: 1.5
              creditAccount:
                type: string
                description: Account that receives the fee credit.
                example: platform-fee-account
              sourceAccount:
                type: string
                description: Account debited for the fee.
                example: sender-account
              isDeductible:
                type: boolean
                description: >-
                  Whether the fee is deducted from the transfer amount (true) or
                  added on top (false).
                example: false
        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
    RecipientDetails:
      type: object
      required:
        - ispb
        - account
        - holderDocument
      properties:
        ispb:
          type: string
          pattern: ^[0-9]{8}$
          description: The 8-digit ISPB code identifying the recipient's bank.
          example: '00000000'
        branch:
          type: string
          pattern: ^[0-9]{4}$
          description: The 4-digit branch code (agência).
          example: '0001'
        account:
          type: string
          pattern: ^[0-9]{1,20}$
          description: The account number, from 1 to 20 digits.
          example: '1234567890'
        accountType:
          $ref: '#/components/schemas/AccountType'
        holderName:
          type: string
          minLength: 1
          maxLength: 200
          description: The full name of the account holder.
          example: Maria Santos
        holderDocument:
          type: string
          pattern: ^[0-9]{11}$|^[0-9]{14}$
          description: >-
            The holder's document number. CPF (11 digits) for individuals or
            CNPJ (14 digits) for companies.
          example: '12345678901'
    InitiationStatus:
      type: string
      enum:
        - PENDING_CONFIRMATION
        - PROCESSED
        - EXPIRED
      description: >-
        The status of the initiation. PENDING_CONFIRMATION indicates the
        initiation is awaiting confirmation via the Process Transfer endpoint.
        PROCESSED indicates a transfer was created. EXPIRED indicates the
        initiation expired after 24 hours.
      example: PENDING_CONFIRMATION
    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
    AccountType:
      type: string
      description: >-
        The account type following ISO 20022 codes. Known values include: CACC
        is a current account (Conta Corrente), SLRY is a salary account (Conta
        Salário), SVGS is a savings account (Conta Poupança), TRAN is a
        transactional account (Conta de Pagamento), and OTHR is any other
        account type.
      example: CACC
  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
    AccountNotFound:
      description: Indicates that the sender account was not found in the CRM.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            accountNotFound:
              summary: Invalid sender account
              value:
                error:
                  code: BTF-0500
                  service: crm
                  category: deterministic
                  message: Sender account does not exist in CRM
                  requestId: 6d3e2a68-1f2b-4c3d-9e4f-5a6b7c8d9e0f
    DuplicateTransfer:
      description: >-
        Indicates that an identical transfer was detected within the 60-second
        deduplication window.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            duplicate:
              summary: Same transfer submitted twice
              value:
                error:
                  code: BTF-0012
                  service: plugin
                  category: deterministic
                  message: Identical transfer submitted 15 seconds ago
                  requestId: 6d3e2a68-1f2b-4c3d-9e4f-5a6b7c8d9e0f
                  fields:
                    originalTransferId: 019c96a0-ab10-7cde-f1a2-0e1f2a3b4c5d
                    detectedAt: '2026-02-01T15:30:15-03:00'
    OperatingHoursViolation:
      description: >-
        Indicates that the transfer was attempted outside BACEN operating hours
        (Monday-Friday, 06:30-17:00 Brasília time).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            outsideHours:
              summary: After 17:00
              value:
                error:
                  code: BTF-0010
                  service: plugin
                  category: deterministic
                  message: >-
                    Transfers can only be initiated Monday-Friday between 06:30
                    and 17:00 Brasília time
                  requestId: 6d3e2a68-1f2b-4c3d-9e4f-5a6b7c8d9e0f
                  fields:
                    currentTime: '2026-02-01T18:30:00-03:00'
                    nextAvailableTime: '2026-02-03T06:30:00-03:00'
    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

````