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

# Submit an RFI

> Send a customer's answers to a request for information with submitRfi, all at once or in parts, and handle per-question validation errors.

## Overview

The **submitRfi** mutation saves a customer's answers to an open RFI.

* With `finalize: true` (the default), the RFI is sent for review and moves to `IN_REVIEW`. Every required question must be answered, in this call or by an earlier saved answer.
* With `finalize: false`, only the answers you send are saved and the RFI stays `PENDING_DOCUMENTS`, so the rest can follow in later calls.

Answers are validated against the RFI's questions either way.

## Required scopes

| Property | Value |
| - | - |
| Endpoint | GraphQL API |
| Authentication | OAuth Bearer Token. Basic auth is not accepted |
| Required Scopes | `MANAGE_RFI` |

Use the same customer's token you read the RFI with. See [Who can answer an RFI](https://docs.fluz.app/rfi-overview#who-can-answer-an-rfi).

## Basic mutation structure

```graphql theme={null}
mutation SubmitRfi($input: SubmitRfiInput!) {
  submitRfi(input: $input) {
    success
    rfiId
    status
    error {
      code
      message
      validationErrors {
        questionId
        code
        message
      }
    }
  }
}
```

## Parameters

### SubmitRfiInput

| Field | Type | Required | Description |
| - | - | - | - |
| `rfiId` | `UUID!` | Yes | The RFI to answer |
| `answers` | `[RfiAnswerInput!]!` | Yes | Answers for questions that do not have a saved answer yet |
| `finalize` | `Boolean` | No | `true` (default): send the RFI for review. `false`: save these answers and keep the RFI open |

### RfiAnswerInput

| Field | Type | Required | Description |
| - | - | - | - |
| `questionId` | `String!` | Yes | From `RfiQuestion.questionId` |
| `value` | `JSON` | — | The answer. Its shape depends on the question type — see [Question types](https://docs.fluz.app/rfi-overview#question-types) |

Send one answer per question. Leave out:

* questions with `isSubmitted: true` (already saved),
* `SECTION_BREAK` questions,
* bank-link and address questions you answered with [completeRfiPlaidLink](https://docs.fluz.app/complete-rfi-plaid-link), unless you are uploading documents for them instead.

## Example variables

```json theme={null}
{
  "input": {
    "rfiId": "7c1e2a90-4b3d-4f6e-9a18-3d5b2c7e8f01",
    "finalize": true,
    "answers": [
      {
        "questionId": "q_formation",
        "value": [
          { "fileId": "b52f0e4a-1c7d-4a9b-8e36-0f2d9c4a7b15" }
        ]
      },
      {
        "questionId": "q_address",
        "value": [
          { "fileId": "e1d94c3b-6a2f-4c8e-b07d-5a9f1e3c2d48" }
        ]
      },
      {
        "questionId": "q_source_of_funds",
        "value": "Other"
      },
      {
        "questionId": "q_source_of_funds_other",
        "value": "Proceeds from the sale of a previous business"
      }
    ]
  }
}
```

## cURL Example

```bash theme={null}
curl -X POST https://transactional-graph.staging.fluzapp.com/api/v1/graphql \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <ACCESS_TOKEN>" \
  -d '{
    "query": "mutation SubmitRfi($input: SubmitRfiInput!) { submitRfi(input: $input) { success rfiId status error { code message validationErrors { questionId code message } } } }",
    "variables": {
      "input": {
        "rfiId": "7c1e2a90-4b3d-4f6e-9a18-3d5b2c7e8f01",
        "answers": [
          { "questionId": "q_source_of_funds", "value": "Business revenue" }
        ]
      }
    }
  }'
```

## Response details

### SubmitRfiResponse

| Field | Type | Description |
| - | - | - |
| `success` | `Boolean!` | `true` when the answers were saved |
| `rfiId` | `UUID!` | The RFI from the input |
| `status` | `RfiStatus` | `IN_REVIEW` when finalized. `PENDING_DOCUMENTS` when `finalize` was `false`. `null` on failure |
| `error` | `SubmitRfiError` | Set when `success` is `false` |

### Success

```json theme={null}
{
  "data": {
    "submitRfi": {
      "success": true,
      "rfiId": "7c1e2a90-4b3d-4f6e-9a18-3d5b2c7e8f01",
      "status": "IN_REVIEW",
      "error": null
    }
  }
}
```

### Validation failure

```json theme={null}
{
  "data": {
    "submitRfi": {
      "success": false,
      "rfiId": "7c1e2a90-4b3d-4f6e-9a18-3d5b2c7e8f01",
      "status": null,
      "error": {
        "code": "RFI_VALIDATION_FAILED",
        "message": "Some answers are invalid.",
        "validationErrors": [
          {
            "questionId": "q_address",
            "code": "REQUIRED",
            "message": "This question is required. Upload a document or link a bank account with completeRfiPlaidLink."
          },
          {
            "questionId": "q_source_of_funds",
            "code": "DUPLICATE_ANSWER",
            "message": "Only one answer per question is allowed."
          }
        ]
      }
    }
  }
}
```

When validation fails, nothing from the call is saved. Fix the listed answers and send the call again.

## Saving in parts

Use `finalize: false` to let a customer leave and come back, or to save each page of a long form as they go.

> [!WARNING]
>
> **Saved answers are final.** Once a question has a saved answer, it is marked `isSubmitted: true` and cannot be changed — sending it again returns `ALREADY_SUBMITTED`. Save an answer only when the customer has confirmed it. The one exception is a Plaid bank link, which [completeRfiPlaidLink](https://docs.fluz.app/complete-rfi-plaid-link) can replace.

* A partial save does not change the RFI's status and does not send it for review.
* Required questions are checked only when you finalize. A finalize call can be just `{ "rfiId": "...", "answers": [] }` if everything required is already saved.
* After finalizing, the RFI is `IN_REVIEW` and further calls return `RFI_NOT_OPEN`. If Fluz needs more, the RFI comes back to `PENDING_DOCUMENTS` with new questions.

## Conditional questions

Questions whose `visibilityCondition` does not hold are skipped:

* they are not required, and
* any answer you send for them is ignored — no error, and nothing is saved.

Visibility is worked out from earlier answers in `ordinal` order, using saved answers and the answers in the same call. See [Conditional questions](https://docs.fluz.app/rfi-overview#conditional-questions).

## Error Codes

### Payload errors

`submitRfi` returns RFI errors in the payload with `success: false`, not in the top-level `errors` array.

| `error.code` | Description | How to resolve |
| - | - | - |
| `ACCESS_DENIED` | The RFI does not exist, or it is not addressed to the token's user and account | Use the token you read the RFI with |
| `RFI_NOT_OPEN` | The RFI is not `PENDING_DOCUMENTS` — it is already in review or finished | Read the RFI to see its status |
| `RFI_EXPIRED` | The RFI has expired | Direct the customer to support |
| `RFI_VALIDATION_FAILED` | One or more answers failed validation. See `validationErrors` | Fix each listed answer and resend |
| `RFI_SUBMIT_FAILED` | Unexpected error | Retry once. If it persists, contact support with the `rfiId` |

### validationErrors codes

| `code` | Description |
| - | - |
| `UNKNOWN_QUESTION` | No answerable question with this `questionId`, or it is a `SECTION_BREAK` |
| `ALREADY_SUBMITTED` | The question already has a saved answer |
| `DUPLICATE_ANSWER` | The same `questionId` appears more than once in `answers` |
| `REQUIRED` | A required question that applies has no answer. Only when finalizing |
| `INVALID_VALUE` | The value does not match the question type — wrong format, not one of the `options`, too many files, a `fileId` uploaded for another question or used twice, or a file type not accepted for the question |

### Top-level errors

These come back in the `errors` array, before the mutation runs.

| Code | Name | Description | How to resolve |
| - | - | - | - |
| `AUTH-0002` | InvalidCredentials | Basic auth was used | Call with a Bearer user token |
| `AUTH-0031` | InvalidScope | The token is missing `MANAGE_RFI` | Add the scope and re-mint the token |

## Best practices

* **Validate in your UI first.** Check formats, options and required fields before calling, so a validation failure is rare.
* **Finalize once.** Save pages with `finalize: false` if you need to, and finalize when the customer presses submit.
* **Show the result.** After `IN_REVIEW`, show an "under review" state and stop prompting for this RFI.

## Related pages

> [card] [Read RFIs](https://docs.fluz.app/get-rfis)
>
> The questions, saved answers and status.

> [card] [Upload RFI documents](https://docs.fluz.app/upload-rfi-document)
>
> Get the `fileId` values for file questions.

> [card] [Answer with a bank link](https://docs.fluz.app/complete-rfi-plaid-link)
>
> Answer bank-statement and proof-of-address questions with Plaid.

> [card] [RFI overview](https://docs.fluz.app/rfi-overview)
>
> Statuses, question types and the full flow.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.