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

# Close Unsettled TED IN Credit

> Use this endpoint to record where an unsettled inbound credit actually went, after a person moved it by hand. An inbound credit is unsettled when its message carries an open retention (neither credited nor returned), or when its devolution sits in `RETAINED` (a return that the tenant never authorized) or `FAILED` (a return that the clearing house refused).

No money moves here, and no ledger or JD call is made. Every outcome names an act performed outside this system, and this endpoint is the record of it:

- `RETURNED`: a person sent the funds back to the paying bank, out of band, under the return control number that the devolution row has kept since the day of receipt.
- `CREDITED`: a person credited the beneficiary.
- `ABSORBED`: the tenant keeps funds that reached neither end.

A credit written down twice, as an open retention and as a `RETAINED` devolution, is closed on both rows in one transaction or on neither. A retention that the poller resolves by itself is refused: the credit lands on its own once the blocking condition lifts, and declaring it settled would tell the tenant to keep money that the service is about to deliver.

This is a tenant-wide administrative action. It requires the `transfers:resolve` permission and a user token, because the closure records which person decided. It does not require the `X-Organization-Id` header. In multi-tenant deployments it is scoped to the caller's resolved tenant database.



## OpenAPI

````yaml /pt/openapi/v3-current/ted.yaml post /v1/transfers/ted-in/unsettled/{messageId}/close
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/ted-in/unsettled/{messageId}/close:
    post:
      tags:
        - Transfers API
      summary: Close Unsettled TED IN Credit
      description: >-
        Use this endpoint to record where an unsettled inbound credit actually
        went, after a person moved it by hand. An inbound credit is unsettled
        when its message carries an open retention (neither credited nor
        returned), or when its devolution sits in `RETAINED` (a return that the
        tenant never authorized) or `FAILED` (a return that the clearing house
        refused).


        No money moves here, and no ledger or JD call is made. Every outcome
        names an act performed outside this system, and this endpoint is the
        record of it:


        - `RETURNED`: a person sent the funds back to the paying bank, out of
        band, under the return control number that the devolution row has kept
        since the day of receipt.

        - `CREDITED`: a person credited the beneficiary.

        - `ABSORBED`: the tenant keeps funds that reached neither end.


        A credit written down twice, as an open retention and as a `RETAINED`
        devolution, is closed on both rows in one transaction or on neither. A
        retention that the poller resolves by itself is refused: the credit
        lands on its own once the blocking condition lifts, and declaring it
        settled would tell the tenant to keep money that the service is about to
        deliver.


        This is a tenant-wide administrative action. It requires the
        `transfers:resolve` permission and a user token, because the closure
        records which person decided. It does not require the
        `X-Organization-Id` header. In multi-tenant deployments it is scoped to
        the caller's resolved tenant database.
      operationId: closeUnsettledTEDInCredit
      parameters:
        - $ref: '#/components/parameters/XIdempotencyKey'
        - name: messageId
          in: path
          required: true
          description: The identifier of the inbound JD message.
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        description: Where the money went, and why.
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CloseUnsettledTEDInCreditRequest'
      responses:
        '200':
          description: Indicates that the closure was recorded.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CloseUnsettledTEDInCreditResponse'
        '400':
          description: >-
            BTF-0001: invalid `messageId`, missing idempotency key, an `outcome`
            other than `RETURNED`, `CREDITED`, or `ABSORBED`, or a `note`
            outside 10 to 500 characters.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDocument'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: >-
            BTF-0405: the caller lacks the `transfers:resolve` permission.
            BTF-0406: the bearer token is not a person (a service account, a
            token of another type, or a user token whose owner or subject is
            blank once trimmed), so this by-hand write cannot be attributed to
            an operator. No grant fixes this; call the endpoint with a user
            token.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDocument'
        '404':
          description: >-
            BTF-0215: this message carries nothing that an operator can close:
            no retention, and no devolution in `RETAINED` or `FAILED`. A message
            that does not exist answers the same code, so the endpoint cannot
            reveal which message IDs a tenant holds.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDocument'
        '409':
          description: >-
            BTF-0216: somebody already recorded where this money went. Read
            their decision before you write another.


            BTF-0217: this retention resolves by itself and must not be closed
            by hand. The credit lands on its own once its ledger route or
            ownership answer arrives, and the remedy is that configuration,
            never this endpoint.


            BTF-0016: a request under this `X-Idempotency` key still holds the
            in-flight lease, because it is still running or because it already
            ended 5xx and recorded no outcome. `Retry-After` carries a poll
            interval, not the lease. While the first request is still running,
            resend the identical request after that interval; the answer replays
            from the first request as soon as it finishes. If an earlier request
            under this key answered 5xx without `X-Idempotency-Fenced: true`, no
            answer will ever be served from it: stop resending, read the
            resource this route acts on, and send the work under a new
            `X-Idempotency` key only if it did not land. The detail also names
            the 15-minute bound after which the lease lapses and a resend runs
            the work a second time; a poll still unanswered by then ends the
            same way.


            BTF-0018: the request under this `X-Idempotency` key already
            completed, and its response was too large to store for replay. Read
            the resource. Do not resend under a new key, because that runs the
            work a second time. This answer carries no `Retry-After`, because no
            wait produces the missing receipt.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDocument'
        '422':
          $ref: '#/components/responses/IdempotencyKeyRefused'
        '429':
          $ref: '#/components/responses/RateLimitExceeded'
        '500':
          description: >-
            BTF-9000: internal server error. BTF-9006: unexpected empty response
            from the service layer.
          headers:
            X-Idempotency-Fenced:
              $ref: '#/components/headers/XIdempotencyFenced'
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDocument'
        '503':
          description: >-
            BTF-9005, BTF-9007, BTF-9008: a dependency or the repository is
            unavailable.


            BTF-9016: this tenant's database does not carry the
            retention-closure columns, and nothing was written. Apply the
            pending migrations to this tenant and send the identical request
            again under a new `X-Idempotency` key.


            BTF-9000: the idempotency store was unavailable before the handler
            ran, so nothing ran. Send the same request again under the same
            `X-Idempotency` key.


            BTF-0019: the work under this `X-Idempotency` key ran, and neither
            its response nor its outcome fence could be stored, so the key
            protects nothing and a resend can run the operation a second time.
            Read the resource before you send anything else.


            BTF-0020: the work under this `X-Idempotency` key ran and its
            response could not be stored for replay, but the key is still held.
            This answer is not the outcome of that work. Read the resource, and
            resend under a new key only if the work did not land.
          headers:
            X-Idempotency-Fenced:
              $ref: '#/components/headers/XIdempotencyFenced'
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/ProblemDocument'
components:
  parameters:
    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:
    CloseUnsettledTEDInCreditRequest:
      type: object
      required:
        - outcome
        - note
      properties:
        outcome:
          type: string
          description: '`RETURNED`, `CREDITED`, or `ABSORBED`. Accepted case-insensitively.'
          example: RETURNED
        note:
          type: string
          minLength: 10
          maxLength: 500
          description: The operator justification.
          example: >-
            funds wired back to the paying bank under control number
            20260901000042; treasury ticket 8812
    CloseUnsettledTEDInCreditResponse:
      type: object
      properties:
        messageId:
          type: string
          format: uuid
          example: 770e8400-e29b-41d4-a716-446655440003
        outcome:
          type: string
          example: RETURNED
        note:
          type: string
          example: >-
            funds wired back to the paying bank under control number
            20260901000042
        amount:
          type: string
          description: >-
            What this decision was worth, read from the retention when the
            message carried one, and from the devolution row otherwise. Omitted
            when no positive amount was parsed.
          example: '15000.00'
        closedAt:
          type: string
          format: date-time
          example: '2026-02-01T15:30:00Z'
        closedBy:
          type: string
          description: The stable subject from the bearer token, never a display name.
          example: acme/ana.souza
        retentionClosed:
          type: boolean
          example: true
        retentionReason:
          type: string
          example: RECIPIENT_NOT_FOUND_RETURN_UNAUTHORIZED
        retainedAt:
          type: string
          format: date-time
          example: '2026-02-01T15:29:55Z'
        devolutionClosed:
          type: boolean
          example: true
        devolutionPreviousStatus:
          type: string
          description: '`RETAINED` or `FAILED`: the devolution status before this call.'
          example: RETAINED
        devolutionStatus:
          type: string
          example: RETURNED
    ProblemDocument:
      type: object
      description: >-
        The RFC 9457 problem document that the service answers every error with,
        on `application/problem+json`. Route-specific members (for example
        `refusalCode`, `transactionId`, `ledgerStatus`, `systemplaneKey`) appear
        flat at the top level beside these.
      additionalProperties: true
      required:
        - type
        - title
        - status
        - detail
        - code
        - requestId
        - service
        - category
      properties:
        type:
          type: string
          description: >-
            A URI that names the error code:
            `https://errors.lerian.studio/v1/<code>`.
          example: https://errors.lerian.studio/v1/BTF-0200
        title:
          type: string
          description: The HTTP status text.
          example: Not Found
        status:
          type: integer
          description: The HTTP status code.
          example: 404
        detail:
          type: string
          description: A human-readable explanation of this occurrence.
          example: transfer not found
        instance:
          type: string
          description: The trace ID of this request, when one was recorded.
          example: 4bf92f3577b34da6a3ce929d0e0e4736
        errors:
          type: array
          description: Each rejected field. Present on field validation errors only.
          items:
            type: object
            properties:
              message:
                type: string
                description: Why the value was rejected.
                example: transferId must be a valid UUID
              location:
                type: string
                description: 'Where the value sits: `body.<field>` or `query.<field>`.'
                example: body.senderAccountId
        code:
          type: string
          description: The stable BTF error code.
          example: BTF-0200
        upstream:
          type: object
          description: >-
            The error that an upstream provider (JD SPB, Midaz) reported. Absent
            unless surfaced.
          properties:
            code:
              type: string
              description: The provider's own error code, verbatim.
              example: AAC90
            message:
              type: string
              description: The provider's own error message, bounded.
              example: Assinatura invalida
        requestId:
          type: string
          description: The request correlation ID. Present even when empty.
          example: 6d3e2a68-1f2b-4c3d-9e4f-5a6b7c8d9e0f
        service:
          type: string
          description: The system that produced the error.
          example: plugin
        category:
          type: string
          description: The machine-readable error category.
          example: deterministic
    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
  responses:
    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
    IdempotencyKeyRefused:
      description: >-
        BTF-0014: an earlier request under this `X-Idempotency` key answered
        5xx, so the key is fenced for the retention window. Read the resource
        and, only if the work did not land, send the identical request under a
        new key.


        BTF-0015: this service cannot read the idempotency record under this
        key. The remedy is the same.


        BTF-0017: this `X-Idempotency` key was already used for a different
        request. A repeat must be byte-identical, and a new request needs its
        own new key. BTF-0017 is decided before BTF-0014, so a fenced key resent
        with a changed body gets BTF-0017.
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDocument'
    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.
  headers:
    XIdempotencyFenced:
      description: >-
        `true` when this 5xx fenced the `X-Idempotency` key, so a resend is
        refused with 422 BTF-0014. `false` when the fence write itself failed
        and only the in-flight lease holds the key, so a resend is refused with
        409 BTF-0016 until that lease lapses. On a 503 BTF-0019, `false` means
        the handler succeeded and both its receipt and its fence were lost.


        The header is absent when nothing fenced the key. On a 500 raised by a
        panic, the protection of the key is unknown: read the resource and
        reconcile before you resend. On a 503 BTF-9000 answered while the
        idempotency store was down before the handler, nothing ran: send the
        same request again under the same key.
      schema:
        type: string
  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

````