> ## 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: 2.4.0
servers:
  - url: https://plugin-br-bank-transfer.sandbox.lerian.net
    description: Sandbox (placeholder — not yet available for public access)
security:
  - BearerAuth: []
tags:
  - name: Transfers API
    description: Endpoints for initiating, processing, tracking, and cancelling transfers.
  - name: Webhook DLQ
    description: Endpoints for inspecting and retrying webhook dead-letter queue messages.
  - name: Health API
    description: Endpoints for checking service liveness and readiness.
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'
        '404':
          $ref: '#/components/responses/AccountNotFound'
        '409':
          $ref: '#/components/responses/DuplicateTransfer'
        '422':
          $ref: '#/components/responses/OperatingHoursViolation'
        '429':
          $ref: '#/components/responses/RateLimitExceeded'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
components:
  parameters:
    XOrganizationId:
      name: X-Organization-Id
      in: header
      required: true
      description: >-
        Organization ID used as the tenant identifier. All data is scoped to
        this organization. Must match the JWT tenantId claim when authentication
        is enabled.
      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
        - branch
        - account
        - accountType
        - holderName
        - 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
            - message
          properties:
            code:
              type: string
              pattern: ^BTF-[0-9]{4}$
              description: The error code in BTF-XXXX format.
              example: BTF-0010
            title:
              type: string
              description: A short, human-readable title for the error.
              example: Operating Hours Violation
            message:
              type: string
              description: A detailed description of the error.
              example: >-
                Transfers can only be initiated Monday-Friday between 06:30 and
                17:00 Brasília time
            fields:
              type: object
              additionalProperties: true
              description: Field-level validation errors for request body parameters.
              example:
                currentTime: '2026-02-01T18:30:00-03:00'
                operatingHours: Mon-Fri 06:30-17:00 UTC-3
            headers:
              type: object
              additionalProperties: true
              description: Validation errors for request headers.
            paths:
              type: object
              additionalProperties: true
              description: Validation errors for path parameters.
            queryParams:
              type: object
              additionalProperties: true
              description: Validation errors for query parameters.
    AccountType:
      type: string
      enum:
        - CACC
        - SLRY
        - SVGS
        - TRAN
        - OTHR
      description: >-
        The account type following ISO 20022 codes. 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
                  title: Invalid Input
                  message: >-
                    The request contains invalid fields. Check the field details
                    below.
                  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
                  title: Unauthorized
                  message: Missing or invalid authentication token
    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
                  title: Account Not Found
                  message: Sender account does not exist in CRM
    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
                  title: Duplicate Transfer
                  message: Identical transfer submitted 15 seconds ago
                  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
                  title: Operating Hours Violation
                  message: >-
                    Transfers can only be initiated Monday-Friday between 06:30
                    and 17:00 Brasília time
                  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-0001
                  title: Invalid input
                  message: >-
                    Too many requests. Retry after the interval indicated by the
                    `Retry-After` header.
              description: >
                Rate-limit responses share the `BTF-0001` code with other 4xx
                validation errors. Clients should detect rate limiting via HTTP
                status `429` and the `Retry-After` header rather than the error
                code.
    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
                  title: CRM Service Unavailable
                  message: >-
                    Unable to validate account. The CRM service is temporarily
                    unavailable. Try again later.
            jdUnavailable:
              summary: JD SPB unavailable
              value:
                error:
                  code: TRANSPORT
                  title: JD SPB Unavailable
                  message: >-
                    Unable to submit transfer. The JD SPB service is temporarily
                    unavailable. Try again later.
            midazUnavailable:
              summary: Midaz ledger unavailable
              value:
                error:
                  code: BTF-2000
                  title: Midaz Unavailable
                  message: >-
                    Unable to process transfer. The Midaz ledger service is
                    temporarily unavailable. Try again later.
            feeServiceUnavailable:
              summary: Fee service unavailable (fail-closed mode)
              value:
                error:
                  code: BTF-3000
                  title: Fee Service Unavailable
                  message: >-
                    Unable to calculate fee. The fee service is temporarily
                    unavailable. Try again later.
            dlqInspectorUnavailable:
              summary: DLQ inspector not configured
              value:
                error:
                  code: BTF-9005
                  title: DLQ Inspector Unavailable
                  message: DLQ inspector is not configured
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: >-
        JWT Bearer token authentication. The token must include a tenantId claim
        that matches the X-Organization-Id header.

````