> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tracefinance.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Upload a beneficiary document

> Uploads a compliance document, such as a custody attestation, for a beneficiary's payment instruction.



## OpenAPI

````yaml apis/fx-payment/openapi.yml POST /v1/beneficiaries/{beneficiaryId}/documents
openapi: 3.1.1
info:
  title: Trace Finance Payments API
  version: 1.0.0
  description: >
    API for deposits, withdrawals, swaps, and beneficiary management on the
    Trace Finance platform.
servers:
  - url: https://api.sandbox.tracefinance.com
    description: Sandbox
security:
  - bearerAuth: []
tags:
  - name: Operations
    description: >-
      Create deposits, withdrawals, and swaps. Query operation status and
      history.
  - name: Reports
    description: Generate aggregated views of operations across a time window.
  - name: Beneficiaries
    description: >-
      Manage external beneficiaries and their payment instructions for
      withdrawals.
  - name: Payment instructions
    description: Add or remove payment instructions on an existing beneficiary.
paths:
  /v1/beneficiaries/{beneficiaryId}/documents:
    post:
      tags:
        - Beneficiaries
      summary: Upload a beneficiary document
      description: >
        Uploads a compliance document to the beneficiary identified by the path
        `beneficiaryId`. Set `holder.type` to `PAYMENT_INSTRUCTION` with the
        payment instruction ID; the document satisfies that instruction's
        compliance review. The instruction must belong to the path beneficiary
        (otherwise `404`) and must be a crypto instruction — the only supported
        document is `CUSTODY_ATTESTATION`, which proves a crypto wallet's
        custody arrangement. Uploading against a non-crypto instruction returns
        `422`.


        The document may also be supplied inline when the beneficiary is
        created; this endpoint covers the submit-later case. The document is
        uploaded as multipart: a JSON `body` part carrying the document type and
        holder, plus a binary `file` part.
      operationId: uploadBeneficiaryDocument
      parameters:
        - $ref: '#/components/parameters/BeneficiaryId'
        - $ref: '#/components/parameters/TraceVersion'
        - $ref: '#/components/parameters/IdempotencyKey'
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                body:
                  $ref: '#/components/schemas/SubmitBeneficiaryDocumentRequest'
                file:
                  type: string
                  format: binary
                  description: Document file content (PDF, JPEG, PNG, DOC or DOCX).
              required:
                - body
                - file
            encoding:
              body:
                contentType: application/json
            examples:
              custodyAttestation:
                summary: Custody attestation for a crypto payment instruction
                value:
                  body:
                    documentType: CUSTODY_ATTESTATION
                    holder:
                      type: PAYMENT_INSTRUCTION
                      referenceId: pi-a1b2c3d4-5e6f-7890-abcd-ef1234567890
      responses:
        '204':
          description: Document uploaded.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/RequestId'
        '400':
          description: Invalid request or missing multipart fields.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/RequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                emptyFile:
                  summary: Uploaded file is empty
                  value:
                    code: EMPTY_FILE
                    message: 'File must not be empty: fieldName=file'
                    details:
                      fieldName: file
                missingMultipartField:
                  summary: Required multipart field is missing
                  value:
                    code: MISSING_MULTIPART_FIELD
                    message: 'Missing required multipart field: fieldName=body'
                    details:
                      fieldName: body
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          description: >
            Beneficiary not found, or the holder does not belong to the path
            beneficiary.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/RequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                beneficiaryNotFound:
                  $ref: '#/components/examples/BeneficiaryNotFound'
                paymentInstructionNotFound:
                  summary: Holder payment instruction does not exist on the beneficiary
                  value:
                    code: RESOURCE_NOT_FOUND
                    message: >-
                      PaymentInstruction with given parameters
                      [id:pi-a1b2c3d4-5e6f-7890-abcd-ef1234567890] not found
                    details:
                      resource: PaymentInstruction
                      parameters:
                        id: pi-a1b2c3d4-5e6f-7890-abcd-ef1234567890
        '422':
          description: Business rule violation.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/RequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                nonCryptoInstruction:
                  summary: Custody attestation targets a non-crypto payment instruction
                  value:
                    code: DOCUMENT_NOT_APPLICABLE
                    message: >-
                      CUSTODY_ATTESTATION is only accepted for CRYPTO payment
                      instructions
                    details:
                      documentType: CUSTODY_ATTESTATION
                      rail: PIX_KEY
components:
  parameters:
    BeneficiaryId:
      name: beneficiaryId
      in: path
      required: true
      description: UUID of the beneficiary.
      schema:
        type: string
        format: uuid
    TraceVersion:
      name: X-Trace-Version
      in: header
      required: false
      description: API version. Omit to use the default version.
      schema:
        type: string
        example: '1'
    IdempotencyKey:
      name: X-Idempotency-Key
      in: header
      required: true
      description: >-
        Unique key to ensure idempotent request processing. Required on all
        `POST`, `PUT`, and `PATCH` requests.
      schema:
        type: string
        format: uuid
  schemas:
    SubmitBeneficiaryDocumentRequest:
      type: object
      description: >-
        Metadata for a compliance document submitted for a beneficiary. Sent as
        the JSON `body` part of the multipart request; the document file itself
        is the `file` part.
      properties:
        documentType:
          $ref: '#/components/schemas/DocumentType'
        holder:
          $ref: '#/components/schemas/DocumentHolderRequest'
        metadata:
          type: object
          additionalProperties:
            type: string
          description: Optional key-value metadata for the document.
      required:
        - documentType
        - holder
    ErrorResponse:
      type: object
      properties:
        code:
          type: string
          description: Machine-readable error code.
        message:
          type: string
          description: Human-readable description.
        details:
          type: object
          additionalProperties: true
      required:
        - code
        - message
    DocumentType:
      type: string
      description: >-
        Type of compliance document. Beneficiary document submission supports
        only `CUSTODY_ATTESTATION`, which proves a crypto wallet's custody
        arrangement.
      enum:
        - CUSTODY_ATTESTATION
      example: CUSTODY_ATTESTATION
    DocumentHolderRequest:
      type: object
      description: >
        Identifies which entity on the beneficiary the document belongs to.
        Today only `PAYMENT_INSTRUCTION` is accepted — the holder is the payment
        instruction whose compliance review the document satisfies. The object
        is shaped to carry other holder kinds in the future; only the value
        below is currently valid.
      properties:
        type:
          type: string
          enum:
            - PAYMENT_INSTRUCTION
          example: PAYMENT_INSTRUCTION
        referenceId:
          type: string
          description: >
            Identifier of the payment instruction the document belongs to. The
            instruction must belong to the beneficiary in the path.
          example: pi-a1b2c3d4-5e6f-7890-abcd-ef1234567890
      required:
        - type
        - referenceId
  headers:
    RequestId:
      description: >-
        Unique request identifier emitted on every response. Reference it when
        contacting Trace Finance support so we can trace the request end-to-end.
        See [Errors](/guides/principles/errors).
      schema:
        type: string
        format: uuid
  responses:
    UnauthorizedError:
      description: Missing or invalid authentication token.
      headers:
        X-Request-Id:
          $ref: '#/components/headers/RequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            invalidToken:
              $ref: '#/components/examples/InvalidToken'
            expiredToken:
              $ref: '#/components/examples/ExpiredToken'
  examples:
    BeneficiaryNotFound:
      summary: Beneficiary does not exist for the authenticated customer
      value:
        code: RESOURCE_NOT_FOUND
        message: >-
          Beneficiary with given parameters
          [id:b2c3d4e5-f6a7-8901-bcde-f12345678901] not found
        details:
          resource: Beneficiary
          parameters:
            id: b2c3d4e5-f6a7-8901-bcde-f12345678901
    InvalidToken:
      summary: Bearer token is invalid or malformed
      value:
        code: INVALID_ACCESS_TOKEN
        message: Invalid access token
        details: {}
    ExpiredToken:
      summary: Bearer token has expired
      value:
        code: EXPIRED_ACCESS_TOKEN
        message: Expired access token
        details: {}
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: >-
        JWT bearer token. Include as `Authorization: Bearer <token>`. See the
        [Authentication](/guides/authentication) guide for how to obtain one.

````