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

# Upload files to a document item

> Answer a `document` item by uploading its files as `multipart/form-data`. One call can carry several, because one thing asked for may be several files.

**Uploading adds to the set; it never replaces it.** A second upload leaves the first file in place.



## OpenAPI

````yaml /openapi/kira-api.2026-04-14.json post /v1/rfis/{rfi_id}/items/{item_id}/documents
openapi: 3.1.0
info:
  title: Kira API
  version: '2026-04-14'
  description: >-
    REST API for users, KYC/KYB verification, virtual accounts, payouts,
    recipients, and webhooks. Every request requires an `x-api-key` header and a
    bearer access token (see Authentication). Pin your account to version
    `2026-04-14` before integrating.
  contact:
    name: Kira API Support
    email: support@kirafin.ai
servers:
  - url: https://api.balampay.com
    description: Production
  - url: https://api.balampay.com/sandbox
    description: Sandbox
security:
  - bearerAuth: []
    apiKeyAuth: []
tags:
  - name: Authentication
  - name: Versioning
  - name: Users
  - name: Virtual Accounts
  - name: Recipients
  - name: Quotations
  - name: Payouts
  - name: Reference
  - name: RFIs
paths:
  /v1/rfis/{rfi_id}/items/{item_id}/documents:
    post:
      tags:
        - RFIs
      summary: Upload files to a document item
      description: >-
        Answer a `document` item by uploading its files as
        `multipart/form-data`. One call can carry several, because one thing
        asked for may be several files.


        **Uploading adds to the set; it never replaces it.** A second upload
        leaves the first file in place.
      operationId: post_v1-rfis-rfi-id-items-item-id-documents
      parameters:
        - in: path
          name: rfi_id
          required: true
          schema:
            type: string
            format: uuid
          description: RFI UUID.
        - in: path
          name: item_id
          required: true
          schema:
            type: string
            format: uuid
          description: Item UUID. The item must be a `document` item of this RFI.
        - in: header
          name: X-Api-Version
          required: false
          description: >-
            Version applied to this request. It wins over your account's pinned
            version — see [Versioning](/using-the-api/versioning).
          schema:
            type: string
            example: '2026-04-14'
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              required:
                - files
              properties:
                files:
                  type: array
                  maxItems: 20
                  items:
                    type: string
                    format: binary
                  description: >-
                    One or more files, repeating the field name once per file.
                    Each is capped at 30 MB. The item's own `answer_spec`
                    narrows what it takes and never widens it: without
                    `mime_types` the accepted set is `application/pdf`,
                    `image/jpeg`, `image/png`, `image/heic` and `image/webp`,
                    and without `max_files` the item holds 20 in total — this
                    call is refused if it would take the item past that.
      responses:
        '201':
          description: The files were stored.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RfiItemDocumentsResponse'
              example:
                item:
                  item_id: 1a2b3c4d-5e6f-4708-9a1b-2c3d4e5f6a7b
                  ordinal: 1
                  prompt: >-
                    Upload the certificate of good standing issued in the last
                    90 days.
                  answer_type: document
                  answer_spec:
                    max_files: 3
                  target_key: null
                  subject: null
                  status: answered
                  answer_value: null
                  documents:
                    - document_id: 9f8e7d6c-5b4a-4321-8765-4321fedcba98
                      file_name: certificate-of-good-standing.pdf
                      mime_type: application/pdf
                      size_bytes: 184320
                      checksum: >-
                        9f2b1c4e8a6d3f705b1e9c8d7a6f5e4d3c2b1a0908f7e6d5c4b3a29180706054
                      uploaded_at: '2026-09-02T09:15:00.000Z'
                  review_note: null
                  updated_at: '2026-09-02T09:15:00.000Z'
                  returned_at: null
        '400':
          description: >-
            An id in the path is not a UUID. Ids are checked before anything is
            looked up, so a malformed one answers `400`, not `404`. This body
            has `error` and `details[]`, and no `code`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ValidationErrorResponse'
              example:
                error: Invalid request data
                details:
                  - path: item_id
                    message: Invalid item ID format
                    code: invalid_string
        '401':
          description: Unauthorized.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                code: invalid_request
                message: >-
                  The request could not be authenticated. Check the x-api-key
                  and Authorization headers.
        '404':
          description: >-
            The request is not visible to you — another client's, or withdrawn —
            or the item does not belong to it. `code` tells them apart.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                rfi_not_found:
                  summary: The request is not yours, or was withdrawn
                  value:
                    statusCode: 404
                    error: Not Found
                    message: RFI not found
                    timestamp: '2026-09-15T10:22:41.117Z'
                    path: >-
                      /v1/rfis/7f1c9a20-3b4d-4e5f-8a91-2c3d4e5f6a7b/items/1a2b3c4d-5e6f-4708-9a1b-2c3d4e5f6a7b/documents
                    code: rfi_not_found
                item_not_found:
                  summary: The item is not on this request
                  value:
                    statusCode: 404
                    error: Not Found
                    message: >-
                      item 1a2b3c4d-5e6f-4708-9a1b-2c3d4e5f6a7b does not belong
                      to rfi 7f1c9a20-3b4d-4e5f-8a91-2c3d4e5f6a7b
                    timestamp: '2026-09-15T10:22:41.117Z'
                    path: >-
                      /v1/rfis/7f1c9a20-3b4d-4e5f-8a91-2c3d4e5f6a7b/items/1a2b3c4d-5e6f-4708-9a1b-2c3d4e5f6a7b/documents
                    code: rfi_item_not_found
        '409':
          description: >-
            The request is closed, and its answers can no longer change. What
            was sent has been reviewed and may already be on the sub-client's
            profile.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                statusCode: 409
                error: Conflict
                message: >-
                  rfi 7f1c9a20-3b4d-4e5f-8a91-2c3d4e5f6a7b is resolved and no
                  longer accepts answers
                timestamp: '2026-09-15T10:22:41.117Z'
                path: >-
                  /v1/rfis/7f1c9a20-3b4d-4e5f-8a91-2c3d4e5f6a7b/items/1a2b3c4d-5e6f-4708-9a1b-2c3d4e5f6a7b/documents
                code: rfi_closed
        '422':
          description: >-
            The item's files are unchanged. Read `code` to know what to change.
            `rfi_documents_invalid`: a type the item does not accept, a file
            over 30 MB, more files than the item holds, or a body that could not
            be read. `rfi_documents_missing`: the multipart body has no file.
            `rfi_document_content_mismatch`: a file's contents do not match its
            declared type, so ask whoever chose the file for another one instead
            of retrying. `rfi_item_not_a_document_item`: this item takes an
            answer value, not files.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                documents_invalid:
                  summary: A file the item does not accept
                  value:
                    statusCode: 422
                    error: Unprocessable Entity
                    message: >-
                      documents: 0.mime_type — image/gif is not one of the
                      accepted types: application/pdf, image/jpeg, image/png,
                      image/heic, image/webp
                    timestamp: '2026-09-15T10:22:41.117Z'
                    path: >-
                      /v1/rfis/7f1c9a20-3b4d-4e5f-8a91-2c3d4e5f6a7b/items/1a2b3c4d-5e6f-4708-9a1b-2c3d4e5f6a7b/documents
                    code: rfi_documents_invalid
                documents_missing:
                  summary: No file in the body
                  value:
                    statusCode: 422
                    error: Unprocessable Entity
                    message: send at least one file
                    timestamp: '2026-09-15T10:22:41.117Z'
                    path: >-
                      /v1/rfis/7f1c9a20-3b4d-4e5f-8a91-2c3d4e5f6a7b/items/1a2b3c4d-5e6f-4708-9a1b-2c3d4e5f6a7b/documents
                    code: rfi_documents_missing
                content_mismatch:
                  summary: The bytes are not the declared type
                  value:
                    statusCode: 422
                    error: Unprocessable Entity
                    message: the file's contents are not the type it was sent as
                    timestamp: '2026-09-15T10:22:41.117Z'
                    path: >-
                      /v1/rfis/7f1c9a20-3b4d-4e5f-8a91-2c3d4e5f6a7b/items/1a2b3c4d-5e6f-4708-9a1b-2c3d4e5f6a7b/documents
                    code: rfi_document_content_mismatch
                not_a_document_item:
                  summary: This item is not answered with files
                  value:
                    statusCode: 422
                    error: Unprocessable Entity
                    message: >-
                      item 1a2b3c4d-5e6f-4708-9a1b-2c3d4e5f6a7b is not answered
                      with files
                    timestamp: '2026-09-15T10:22:41.117Z'
                    path: >-
                      /v1/rfis/7f1c9a20-3b4d-4e5f-8a91-2c3d4e5f6a7b/items/1a2b3c4d-5e6f-4708-9a1b-2c3d4e5f6a7b/documents
                    code: rfi_item_not_a_document_item
      security:
        - bearerAuth: []
          apiKeyAuth: []
      servers:
        - url: https://api.balampay.com/sandbox
          description: Sandbox
        - url: https://api.balampay.com
          description: Production
components:
  schemas:
    RfiItemDocumentsResponse:
      type: object
      properties:
        item:
          $ref: '#/components/schemas/RfiItem'
    ValidationErrorResponse:
      type: object
      description: >-
        Validation / request error. The body shape is **not uniform** across the
        API — it varies by endpoint and by which validation layer rejects the
        request. The fields below are the union of what may appear; treat them
        all as optional. Observed shapes include `{ code, message }`, `{ code,
        message, errors[] }`, `{ code, error, details[] }`, `{ error, details[]
        }`, and a nested `{ error: { code, message, details } }`. Always branch
        on the HTTP status, not on a fixed body shape.
      properties:
        code:
          type: string
        message:
          type: string
        error:
          type:
            - string
            - object
          description: >-
            A short error label (e.g. `"Invalid data"`), or on some endpoints a
            nested `{ code, message, details }` object.
        errors:
          type: array
          items:
            type: object
            properties:
              field:
                type: string
              message:
                type: string
            required:
              - field
              - message
        details:
          type:
            - array
            - object
          description: >-
            Per-issue detail. Shape varies by endpoint — typically an array of
            `{ message }` or `{ path, message, code }`, occasionally an object.
    ErrorResponse:
      type: object
      properties:
        message:
          type: string
        code:
          type: string
        statusCode:
          type: number
        error:
          type: string
        timestamp:
          type: string
        path:
          type: string
        details: {}
      required:
        - message
    RfiItem:
      type: object
      description: >-
        One thing being asked for. The addressable unit of an RFI — a `PATCH` or
        a document upload always names an `item_id`, never the parent RFI.
      properties:
        item_id:
          type: string
          format: uuid
        ordinal:
          type: integer
          description: Display order within the RFI.
        prompt:
          type: string
          description: What is being asked, in prose.
        answer_type:
          type: string
          enum:
            - text_long
            - text_short
            - number
            - date
            - boolean
            - choice
            - identifier
            - document
            - ubo_link
          description: >-
            What the item is asking for, and therefore what a valid answer looks
            like. See [RFI values](/reference/rfis/values#answer_type).
        answer_spec:
          type: object
          additionalProperties: true
          description: >-
            The complete set of rules this item validates an answer against, not
            a suggestion. Which keys it holds is fixed by `answer_type` — see
            [RFI values](/reference/rfis/values#answer_spec-by-answer-type).
          example:
            options:
              - ssn
              - itin
        target_key:
          type:
            - string
            - 'null'
          description: >-
            The named subclient field this answer writes on acceptance (e.g.
            `ein`), or `null` when the answer lives only on this item.
        subject:
          type:
            - object
            - 'null'
          description: >-
            Who the item is about. `null` for the sub-client itself; otherwise
            the associated person it names.
          properties:
            person_id:
              type: string
              description: >-
                The `person_id` of the entry in the subclient's
                `associated_persons`.
            display_name:
              type:
                - string
                - 'null'
              description: >-
                The person's name as currently stored — first, middle and last —
                or `null` when they can no longer be found.
          example:
            person_id: 3f1c2a9b7e0d4c6a8b5f1e2d3c4b5a69
            display_name: María López
          required:
            - person_id
            - display_name
        status:
          type: string
          enum:
            - pending
            - answered
          description: >-
            Whether this item is answered. An item has no ending of its own —
            whether the request is satisfied is the request's own `status`. See
            [RFI values](/reference/rfis/values#item-status).
        answer_value:
          type:
            - string
            - number
            - boolean
            - 'null'
          description: >-
            The answer recorded, in the shape `answer_type` expects. `null` on a
            `document` item, whose answer lives in `documents`.
        documents:
          type: array
          items:
            $ref: '#/components/schemas/RfiDocument'
          description: Always present; empty unless `answer_type` is `document`.
        review_note:
          type:
            - string
            - 'null'
          description: >-
            Why the item was sent back for another answer. Cleared the next time
            it is answered.
        updated_at:
          type:
            - string
            - 'null'
          format: date-time
          description: >-
            When this item was last answered. Moves on every round, whether or
            not it changes the item's status.
        returned_at:
          type:
            - string
            - 'null'
          format: date-time
          description: >-
            When the item was last sent back for another answer. `null` if it
            never has been, including while it is under review.
    RfiDocument:
      type: object
      properties:
        document_id:
          type: string
          format: uuid
        file_name:
          type: string
          description: >-
            The name the file was uploaded under, sanitized. This is the name it
            downloads as — the internal storage path is never exposed.
          example: january.pdf
        mime_type:
          type: string
          example: application/pdf
        size_bytes:
          type: integer
        checksum:
          type: string
          description: >-
            SHA-256 of the file's contents, in lower-case hex. Compare it to
            know a file you are holding is the one on the item.
        uploaded_at:
          type: string
          format: date-time
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: >-
        The `data.access_token` value from [Get access
        token](/api-reference/authentication/get-access-token).
    apiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key
      description: API key issued by Kira.

````