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

# Answer an information request

> Step 2 of answering an information request: submit the customer's
answers and attach the documents you uploaded. Requires the
**`cases:write`** scope.

A request is answered **once** — `pending → answered`, no amend, no
re-open; a follow-up is a new request. At least one field or one
document is required.

`fields` is an **ordered array** of `{key, value, label?}`. Keys are
identifiers, unique across the array, and the console shows the answers
in the order you send them.

Every `uploadId` must have been minted for **this** request, must still
be unexpired and unattached, and its object must already be in the
bucket with the declared size and content type. A minted-but-never-
uploaded slot fails the whole submission — nothing is recorded
partially.

A successful answer publishes
[`case.rfi_answered`](/api-reference/webhooks#rfi-answered) and, when
the request was raised by an awaiting **Information request** workflow
node, resumes the workflow with the answers available to its rules.




## OpenAPI

````yaml /api-reference/openapi.yaml post /cases/{caseId}/rfi/{rfiId}/response
openapi: 3.1.0
info:
  title: Frayme Case API
  version: 1.0.0
  description: >
    The partner-facing HTTP API for the Frayme fraud-analysis platform. Submit

    **cases** (KYC, KYB, or Transaction), poll their status, act on paused

    workflow nodes, and deliver external callbacks.


    All requests authenticate with a tenant-scoped API key sent in the

    `X-API-Key` header. Each key carries one or more **scopes** — the required

    scope is listed on every operation below.


    | Scope | Grants |

    | --- | --- |

    | `cases:write` | Submit new cases, and answer an information request |

    | `cases:read` | Read a case, list paused nodes, list durable actions |

    | `cases:callback` | Deliver an external callback, or invoke a pending /
    durable action |

    | `tags:read` | List a case's tags (`GET /cases/{caseId}/tags`) |

    | `tags:write` | Add or remove a case's tags (`POST` / `DELETE
    /cases/{caseId}/tags`) |


    Your tenant is derived from the API key — never send `tenantId` in a request

    body; it is ignored. The base URL and your webhook configuration are

    provisioned for you by Frayme.
servers:
  - url: https://core.us.api.frayme.io
    description: Production.
  - url: https://core.us.api.stg.frayme.io
    description: Staging.
security:
  - apiKeyAuth: []
tags:
  - name: Cases
    description: Submit and read cases.
  - name: Pending actions
    description: Act on a workflow node that is paused awaiting an external system.
  - name: Durable actions
    description: Invoke a broker action on a case after it has been decided.
  - name: Callbacks
    description: Deliver the result of an external callback back to a paused node.
  - name: Information requests
    description: Record a customer's reply to a request for information.
  - name: Tags
    description: Read and manage the labels applied to a case.
paths:
  /cases/{caseId}/rfi/{rfiId}/response:
    post:
      tags:
        - Information requests
      summary: Answer an information request
      description: |
        Step 2 of answering an information request: submit the customer's
        answers and attach the documents you uploaded. Requires the
        **`cases:write`** scope.

        A request is answered **once** — `pending → answered`, no amend, no
        re-open; a follow-up is a new request. At least one field or one
        document is required.

        `fields` is an **ordered array** of `{key, value, label?}`. Keys are
        identifiers, unique across the array, and the console shows the answers
        in the order you send them.

        Every `uploadId` must have been minted for **this** request, must still
        be unexpired and unattached, and its object must already be in the
        bucket with the declared size and content type. A minted-but-never-
        uploaded slot fails the whole submission — nothing is recorded
        partially.

        A successful answer publishes
        [`case.rfi_answered`](/api-reference/webhooks#rfi-answered) and, when
        the request was raised by an awaiting **Information request** workflow
        node, resumes the workflow with the answers available to its rules.
      operationId: submitRfiResponse
      parameters:
        - $ref: '#/components/parameters/CaseId'
        - $ref: '#/components/parameters/RfiId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RFIResponseRequest'
            example:
              fields:
                - key: occupation
                  value: Software engineer
                - key: monthly_income_eur
                  value: 6500
                  label: Monthly income
              documents:
                - uploadId: 9a2e4d71-0b83-4c17-8f5a-1d6e7c0b3a49
                  label: Proof of address
      responses:
        '200':
          description: The request is answered.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RFIAnswer'
              example:
                rfiId: 6f1c0b6e-6a1e-4a3d-9a5e-2f7f0f9f1b21
                status: answered
                answeredAt: '2026-09-16T09:41:07Z'
                fieldCount: 2
                documentCount: 1
        '400':
          description: >-
            Invalid JSON body; an empty `documents[].uploadId`; the same
            `uploadId` twice in one submission; a `documents[].label` over 256
            bytes; or a submission carrying neither a field nor a document.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: No API key was supplied.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: The API key is missing the `cases:write` scope.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: No such case or information request for this tenant.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '409':
          description: >-
            `already_answered` — the body carries `answeredBy` (`apikey:<keyId>`
            when a key answered, so a retry after a lost response recognises its
            own answer, or `analyst` when an analyst recorded the reply in the
            console) and `answeredAt` — or `not_pending`, `case_terminal`,
            `dry_run`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RFIError'
              example:
                error: already_answered
                answeredBy: apikey:key_01HABCXYZ
                answeredAt: '2026-09-16T09:41:07Z'
        '422':
          description: >-
            `document_not_uploaded` (with `uploadId` and a `message`) — the
            object is missing or does not match the declared size and type, or
            the slot was minted for another request, already attached, or
            expired. `invalid_field_key` (a malformed **or repeated** key) /
            `invalid_field_value` (with `key`), `fields_too_large`, or
            `too_many_documents` — more than 10 documents in one submission.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RFIError'
              example:
                error: document_not_uploaded
                uploadId: 9a2e4d71-0b83-4c17-8f5a-1d6e7c0b3a49
                message: object not found
components:
  parameters:
    CaseId:
      name: caseId
      in: path
      required: true
      description: The case identifier returned by `POST /cases`.
      schema:
        type: string
    RfiId:
      name: rfiId
      in: path
      required: true
      description: >-
        The information request's id, delivered as `rfi_id` on the
        `case.rfi_requested` webhook.
      schema:
        type: string
        format: uuid
  schemas:
    RFIResponseRequest:
      type: object
      description: At least one field or one document is required.
      properties:
        fields:
          type: array
          maxItems: 100
          description: >-
            The **scalar** answers, in display order — the console renders them
            in the order you send them. At most 100 entries, 4 KB per value, and
            16 KB in total with labels counted in.
          items:
            type: object
            required:
              - key
            properties:
              key:
                type: string
                pattern: ^[A-Za-z_][A-Za-z0-9_]*$
                description: >-
                  The identifier your workflow rules match on. Unique across the
                  array — a repeated key is `422 invalid_field_key`, never a
                  silent last-one-wins.
              value:
                type:
                  - string
                  - number
                  - boolean
                  - 'null'
                description: >-
                  Scalar only (string, number, boolean, null). Omitting it
                  records the answer as null.
              label:
                type: string
                maxLength: 256
                description: >-
                  An optional human display name for the console, at most 256
                  **bytes**, counted against the same 16 KB total. Display-only
                  — never bound into the workflow, so rules keep matching on the
                  key.
        documents:
          type: array
          maxItems: 10
          items:
            type: object
            required:
              - uploadId
            properties:
              uploadId:
                type: string
                format: uuid
                description: A slot minted for **this** request and already uploaded to.
              label:
                type: string
                maxLength: 256
                description: An optional display name for the document.
    RFIAnswer:
      type: object
      properties:
        rfiId:
          type: string
          format: uuid
        status:
          type: string
          enum:
            - answered
        answeredAt:
          type: string
          format: date-time
        fieldCount:
          type: integer
        documentCount:
          type: integer
    Error:
      type: object
      properties:
        error:
          type: string
          description: A human-readable error message.
    RFIError:
      type: object
      description: >-
        The error shape returned by the information-request response endpoints.
        Unlike `Error`, its `error` is a stable **machine-readable code** you
        branch on, and the remaining properties are the facts you need to
        recover — each present only on the codes described in the response
        above.
      properties:
        error:
          type: string
          description: >-
            The machine-readable code, for example `already_answered`,
            `not_pending`, `case_terminal`, `dry_run`, `too_many_documents`,
            `document_not_uploaded`, `invalid_field_key`, `invalid_field_value`,
            `fields_too_large`.
        answeredBy:
          type: string
          description: >-
            On `already_answered`, `apikey:<keyId>` when a key answered — so a
            retry after a lost response recognises its own answer — or the bare
            string `analyst` when an analyst recorded the reply in the console.
        answeredAt:
          type: string
          format: date-time
          description: On `already_answered`, when the request was answered.
        uploadId:
          type: string
          format: uuid
          description: On `document_not_uploaded`, the slot that failed.
        key:
          type: string
          description: On `invalid_field_key` / `invalid_field_value`, the offending key.
        message:
          type: string
          description: An optional human-readable detail.
  securitySchemes:
    apiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
      description: A tenant-scoped API key provisioned by Frayme.

````