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

# Enviar un RFI

> Envía las respuestas de un cliente a una solicitud de información con submitRfi, todas a la vez o por partes, y maneja los errores de validación por pregunta.

## Descripción general

La mutación **submitRfi** guarda las respuestas de un cliente a un RFI abierto.

* Con `finalize: true` (el valor predeterminado), el RFI se envía a revisión y pasa a `IN_REVIEW`. Todas las preguntas obligatorias deben estar respondidas, ya sea en esta llamada o mediante una respuesta guardada previamente.
* Con `finalize: false`, solo se guardan las respuestas que envías y el RFI permanece en `PENDING_DOCUMENTS`, de modo que el resto puede enviarse en llamadas posteriores.

En ambos casos, las respuestas se validan contra las preguntas del RFI.

## Scopes requeridos

| Propiedad | Valor |
| - | - |
| Endpoint | GraphQL API |
| Autenticación | OAuth Bearer Token. No se acepta autenticación básica |
| Scopes requeridos | `MANAGE_RFI` |

Usa el token del mismo cliente con el que leíste el RFI. Consulta [Quién puede responder un RFI](https://docs.fluz.app/rfi-overview#who-can-answer-an-rfi).

## Estructura básica de la mutación

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

## Parámetros

### SubmitRfiInput

| Campo | Tipo | Requerido | Descripción |
| - | - | - | - |
| `rfiId` | `UUID!` | Sí | El RFI que se va a responder |
| `answers` | `[RfiAnswerInput!]!` | Sí | Respuestas para las preguntas que aún no tienen una respuesta guardada |
| `finalize` | `Boolean` | No | `true` (predeterminado): envía el RFI a revisión. `false`: guarda estas respuestas y mantiene el RFI abierto |

### RfiAnswerInput

| Campo | Tipo | Requerido | Descripción |
| - | - | - | - |
| `questionId` | `String!` | Sí | Proviene de `RfiQuestion.questionId` |
| `value` | `JSON` | — | La respuesta. Su forma depende del tipo de pregunta — consulta [Tipos de preguntas](https://docs.fluz.app/rfi-overview#question-types) |

Envía una respuesta por pregunta. Omite:

* las preguntas con `isSubmitted: true` (ya guardadas),
* las preguntas `SECTION_BREAK`,
* las preguntas de vinculación bancaria y de dirección que respondiste con [completeRfiPlaidLink](https://docs.fluz.app/complete-rfi-plaid-link), a menos que en su lugar estés subiendo documentos para ellas.

## Variables de ejemplo

```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"
      }
    ]
  }
}
```

## Ejemplo con cURL

```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" }
        ]
      }
    }
  }'
```

## Detalles de la respuesta

### SubmitRfiResponse

| Campo | Tipo | Descripción |
| - | - | - |
| `success` | `Boolean!` | `true` cuando las respuestas se guardaron |
| `rfiId` | `UUID!` | El RFI del input |
| `status` | `RfiStatus` | `IN_REVIEW` cuando se finaliza. `PENDING_DOCUMENTS` cuando `finalize` fue `false`. `null` en caso de fallo |
| `error` | `SubmitRfiError` | Se establece cuando `success` es `false` |

### Éxito

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

### Fallo de validación

```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."
          }
        ]
      }
    }
  }
}
```

Cuando la validación falla, no se guarda nada de la llamada. Corrige las respuestas indicadas y vuelve a enviar la llamada.

## Guardado por partes

Usa `finalize: false` para permitir que un cliente se vaya y regrese, o para guardar cada página de un formulario largo a medida que avanza.

> [!WARNING]
>
> **Las respuestas guardadas son definitivas.** Una vez que una pregunta tiene una respuesta guardada, se marca como `isSubmitted: true` y no se puede cambiar: si la envías de nuevo, se devuelve `ALREADY_SUBMITTED`. Guarda una respuesta solo cuando el cliente la haya confirmado. La única excepción es una vinculación bancaria de Plaid, que [completeRfiPlaidLink](https://docs.fluz.app/complete-rfi-plaid-link) puede reemplazar.

* Un guardado parcial no cambia el estado del RFI ni lo envía a revisión.
* Las preguntas obligatorias solo se verifican cuando finalizas. Una llamada de finalización puede ser simplemente `{ "rfiId": "...", "answers": [] }` si todo lo obligatorio ya está guardado.
* Después de finalizar, el RFI queda en `IN_REVIEW` y las llamadas posteriores devuelven `RFI_NOT_OPEN`. Si Fluz necesita más información, el RFI vuelve a `PENDING_DOCUMENTS` con nuevas preguntas.

## Preguntas condicionales

Las preguntas cuya `visibilityCondition` no se cumple se omiten:

* no son obligatorias, y
* cualquier respuesta que envíes para ellas se ignora: sin error y sin que se guarde nada.

La visibilidad se determina a partir de las respuestas anteriores en orden de `ordinal`, usando las respuestas guardadas y las respuestas de la misma llamada. Consulta [Preguntas condicionales](https://docs.fluz.app/rfi-overview#conditional-questions).

## Códigos de error

### Errores en el payload

`submitRfi` devuelve los errores del RFI en el payload con `success: false`, no en el arreglo `errors` de nivel superior.

| `error.code` | Descripción | Cómo resolverlo |
| - | - | - |
| `ACCESS_DENIED` | El RFI no existe, o no está dirigido al usuario y la cuenta del token | Usa el token con el que leíste el RFI |
| `RFI_NOT_OPEN` | El RFI no está en `PENDING_DOCUMENTS`: ya está en revisión o finalizado | Lee el RFI para ver su estado |
| `RFI_EXPIRED` | El RFI ha expirado | Dirige al cliente a soporte |
| `RFI_VALIDATION_FAILED` | Una o más respuestas no pasaron la validación. Consulta `validationErrors` | Corrige cada respuesta indicada y vuelve a enviar |
| `RFI_SUBMIT_FAILED` | Error inesperado | Reintenta una vez. Si persiste, contacta a soporte con el `rfiId` |

### Códigos de validationErrors

| `code` | Descripción |
| - | - |
| `UNKNOWN_QUESTION` | No existe una pregunta respondible con este `questionId`, o es una `SECTION_BREAK` |
| `ALREADY_SUBMITTED` | La pregunta ya tiene una respuesta guardada |
| `DUPLICATE_ANSWER` | El mismo `questionId` aparece más de una vez en `answers` |
| `REQUIRED` | Una pregunta obligatoria que aplica no tiene respuesta. Solo al finalizar |
| `INVALID_VALUE` | El valor no coincide con el tipo de pregunta: formato incorrecto, no es una de las `options`, demasiados archivos, un `fileId` subido para otra pregunta o usado dos veces, o un tipo de archivo no aceptado para la pregunta |

### Errores de nivel superior

Estos se devuelven en el arreglo `errors`, antes de que se ejecute la mutación.

| Código | Nombre | Descripción | Cómo resolverlo |
| - | - | - | - |
| `AUTH-0002` | InvalidCredentials | Se usó autenticación básica | Llama con un token de usuario Bearer |
| `AUTH-0031` | InvalidScope | Al token le falta `MANAGE_RFI` | Agrega el scope y vuelve a generar el token |

## Mejores prácticas

* **Valida primero en tu interfaz.** Verifica formatos, opciones y campos obligatorios antes de llamar, para que un fallo de validación sea poco frecuente.
* **Finaliza una sola vez.** Guarda las páginas con `finalize: false` si lo necesitas, y finaliza cuando el cliente presione enviar.
* **Muestra el resultado.** Después de `IN_REVIEW`, muestra un estado de "en revisión" y deja de solicitar información para este RFI.

## Páginas relacionadas

> [card] [Leer RFIs](https://docs.fluz.app/get-rfis)
>
> Las preguntas, las respuestas guardadas y el estado.

> [card] [Subir documentos de RFI](https://docs.fluz.app/upload-rfi-document)
>
> Obtén los valores de `fileId` para las preguntas de archivos.

> [card] [Responder con una vinculación bancaria](https://docs.fluz.app/complete-rfi-plaid-link)
>
> Responde las preguntas de estado de cuenta bancario y comprobante de domicilio con Plaid.

> [card] [Descripción general de RFI](https://docs.fluz.app/rfi-overview)
>
> Estados, tipos de preguntas y el flujo completo.


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