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

# Subir documentos con carga directa

> Cómo subir documentos directamente a Trébol cuando no tienes una URL de descarga accesible.

Este flujo te permite crear una verificación sin proporcionar una `file_url` al inicio. En su lugar, Trébol te dará una URL para que subas el documento directamente. Este método es útil si los documentos se generan dinámicamente o se encuentran en un almacenamiento privado.

## La experiencia de carga

Inicia la verificación, envía los documentos y confirma la carga. Trébol procesa
cada documento según el tipo de ítem y entrega los resultados a tu aplicación.

<img src="https://mintcdn.com/trebol/bTMEnrdMPLXm5H2E/images/carga-directa/vision-producto-es-light.png?fit=max&auto=format&n=bTMEnrdMPLXm5H2E&q=85&s=f38a45f01231958ebbf2a8846d1ec041" alt="Flujo de carga: iniciar la verificación, enviar documentos, confirmar la carga y recibir resultados." className="block dark:hidden" width="3496" height="1351" data-path="images/carga-directa/vision-producto-es-light.png" />

<img src="https://mintcdn.com/trebol/bTMEnrdMPLXm5H2E/images/carga-directa/vision-producto-es-dark.png?fit=max&auto=format&n=bTMEnrdMPLXm5H2E&q=85&s=ab91429a580a7a10206e4860af3779cb" alt="Flujo de carga: iniciar la verificación, enviar documentos, confirmar la carga y recibir resultados." className="hidden dark:block" width="3496" height="1351" data-path="images/carga-directa/vision-producto-es-dark.png" />

<a href="/docs/images/carga-directa/vision-producto-es-light.png" className="block dark:hidden">Ver el diagrama a tamaño completo</a>

<a href="/docs/images/carga-directa/vision-producto-es-dark.png" className="hidden dark:block">Ver el diagrama a tamaño completo</a>

<Info>
  Este flujo aplica a `generic` (clasificación), `doc_validation` (validación),
  tipos directos de extracción (por ejemplo, `ac_mx`, `csf_mx`,
  `person_id`, `bank_statement` o `property_deed`) y `doc_splitter` (separación
  de documentos). También aplica a los tipos personalizados `cit_...` habilitados
  para tu cuenta. Los items de consulta, como `siger` o `rues`,
  mantienen sus parámetros de consulta y no reciben una URL de carga.
</Info>

<Note>
  Si la verificación usa `options.require_files_for_generic_items: true`, los
  items `generic` sin `file_url` se excluyen al crearla y no reciben una URL de
  carga. Esta restricción existente no aplica a `doc_validation` ni a los otros
  tipos de documento. Para usar carga directa con `generic`, envía `options.require_files_for_generic_items: false` al crear la verificación.
</Note>

El proceso consta de tres pasos:

1. **Crear la verificación o agregar items**: Envías la solicitud inicial a Trébol para registrar la verificación y recibir una URL de carga.
2. **Subir el documento**: Usas la URL proporcionada para subir tu archivo de forma segura.
3. **Confirmar la carga**: Notificas a Trébol que el archivo está listo para ser procesado.

<Accordion title="Ver el flujo técnico de integración">
  El diagrama muestra los intercambios entre tu aplicación, la API de Trébol y
  el almacenamiento de archivos. El procesamiento empieza después de confirmar
  la carga, no al terminar de subir el archivo.

  <img src="https://mintcdn.com/trebol/bTMEnrdMPLXm5H2E/images/carga-directa/flujo-tecnico-es-light.png?fit=max&auto=format&n=bTMEnrdMPLXm5H2E&q=85&s=80d7e4a74f161d2290190bd1b3b97045" alt="Secuencia técnica: solicitar una URL de carga, subir el archivo, confirmar con uploaded_file y recibir el resultado por webhook o consultar el ítem." className="block dark:hidden" width="3151" height="3622" data-path="images/carga-directa/flujo-tecnico-es-light.png" />

  <img src="https://mintcdn.com/trebol/bTMEnrdMPLXm5H2E/images/carga-directa/flujo-tecnico-es-dark.png?fit=max&auto=format&n=bTMEnrdMPLXm5H2E&q=85&s=bc8f6212d2e531ce33834c388901f59b" alt="Secuencia técnica: solicitar una URL de carga, subir el archivo, confirmar con uploaded_file y recibir el resultado por webhook o consultar el ítem." className="hidden dark:block" width="3151" height="3622" data-path="images/carga-directa/flujo-tecnico-es-dark.png" />

  <a href="/docs/images/carga-directa/flujo-tecnico-es-light.png" className="block dark:hidden">Ver el diagrama a tamaño completo</a>

  <a href="/docs/images/carga-directa/flujo-tecnico-es-dark.png" className="hidden dark:block">Ver el diagrama a tamaño completo</a>
</Accordion>

***

## Paso 1: Crear la verificación sin `file_url`

Crea la verificación como lo harías normalmente, pero **omite el atributo `file_url`** en las opciones del item. Trébol detecta que el archivo no está disponible y devuelve una `upload_url` única por item para que subas el archivo directamente.

**Endpoint:** `POST /verifications`

Usa la URL base de la API y la API key de tu ambiente. Los ejemplos siguientes
usan producción (`https://api.gotrebol.com`); reemplaza `YOUR_API_KEY` por tu clave.
Consulta [Errores de la API](/docs/guia-devs/errores) si recibes una respuesta de error.

```bash theme={"dark"}
curl --fail-with-body -X POST "https://api.gotrebol.com/verifications" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  --data '{"country":"mx","tag":"upload-example","items":[{"type":"doc_validation","options":{"client_item_type":"ac_mx"}}]}'
```

Omite `file_url` y conserva las demás opciones requeridas por el tipo. En particular,
`doc_validation` sigue requiriendo `options.client_item_type`. Un item sin archivo
permanece en estado `pending` hasta que completes la carga y la confirmes.

```json theme={"dark"}
{
  "country": "mx",
  "tag": "some-tag-for-my-user",
  "items": [
    {
      "type": "doc_validation",
      "options": { "client_item_type": "ac_mx" }
    }
  ]
}
```

Trébol responde con el `id` de la verificación y una lista de `items`. Cada item de documento tiene su propio `id` y `item_options.upload_url`:

```json theme={"dark"}
{
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "status": "pending",
  "items": [
    {
      "id": 29639,
      "item_type": "doc_validation",
      "item_status": "pending",
      "item_options": {
        "upload_url": "https://files.gotrebol.com/uploads/ITEM_ID_original_file?SIGNED_PARAMETERS"
      }
    }
  ]
}
```

Guarda el `id` del item — lo necesitas en el Paso 3. En los requests usas `type`
y `options`; en las respuestas estos campos se llaman `item_type` e `item_options`.
Las URLs de los ejemplos son ilustrativas: usa siempre la URL completa que recibas.

Para agregar documentos a una verificación existente, usa `PUT /verifications/{id}/add-items`
con el mismo arreglo `items`, sin `country` ni `tag`. Reemplaza `VERIFICATION_ID`
por el ID de la verificación:

```bash theme={"dark"}
curl --fail-with-body -X PUT "https://api.gotrebol.com/verifications/VERIFICATION_ID/add-items" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  --data '{"items":[{"type":"ac_mx","options":{}},{"type":"doc_splitter","options":{}}]}'
```

El cuerpo de esta solicitud es:

```json theme={"dark"}
{
  "items": [
    { "type": "ac_mx", "options": {} },
    { "type": "doc_splitter", "options": {} }
  ]
}
```

Este endpoint devuelve directamente un arreglo de items, cada uno con su `id` y
`item_options.upload_url`. Sigue los pasos 2 y 3 para cada archivo. Los items `cc_co_ops`
que incluyen `options.nit` conservan su flujo de consulta existente. Este tipo
también admite documentos; la opción `nit` selecciona la consulta y evita que
el item espere una carga manual.

Por ejemplo, la respuesta de add-items es un arreglo:

```json theme={"dark"}
[
  {
    "id": 29640,
    "item_type": "ac_mx",
    "item_status": "pending",
    "item_options": {
      "upload_url": "https://files.gotrebol.com/uploads/ITEM_ID_original_file?SIGNED_PARAMETERS"
    }
  }
]
```

Ver detalle del endpoint y atributos en [Crear una verificación](/docs/guia-devs/crear-verificaciones/via-api/crear-verificacion).

***

## Paso 2: Subir el documento

Con la `upload_url` recibida, sube el documento correspondiente mediante una solicitud `PUT`.

<Warning>
  La URL es temporal: usa el valor completo recibido, incluidos sus parámetros
  de firma. Actualmente expira después de una hora. Si expira, consulta
  `GET /verification-items/{id}` para obtener una nueva `item_options.upload_url`.
  La URL no se invalida automáticamente después de un PUT; confirma la carga
  cuando hayas terminado de subir el archivo.
</Warning>

**Endpoint:** `PUT` a la `upload_url` del `item`.

Esta URL ya está firmada: no envíes `x-api-key` al servidor de archivos.

**Headers:**

* `Content-Type`: El tipo MIME del archivo (ej. `application/pdf`, `image/jpeg`).

**Body:**
El contenido binario del archivo.

<CodeGroup>
  ```bash cURL theme={"dark"}
  curl --fail-with-body -X PUT "https://files.gotrebol.com/uploads/ITEM_ID_original_file?SIGNED_PARAMETERS" \
  -H "Content-Type: application/pdf" \
  --data-binary @"/ruta/a/tu/documento.pdf"
  ```

  ```javascript Node.js theme={"dark"}
  import { readFile } from "node:fs/promises";
  // Replace these values with the complete upload URL and your local file path.
  const uploadUrl = "https://files.gotrebol.com/uploads/ITEM_ID_original_file?SIGNED_PARAMETERS";
  const filePath = "/ruta/a/tu/documento.pdf";
  const response = await fetch(uploadUrl, {
    method: "PUT",
    headers: { "Content-Type": "application/pdf" },
    body: await readFile(filePath),
  });
  if (!response.ok) throw new Error(`Upload failed: ${response.status}`);
  ```
</CodeGroup>

Una carga exitosa devolverá un código de estado `200 OK`.

### Si tu sistema almacena el documento en Base64

Decodifica la cadena en tu cliente y envía los bytes resultantes a `upload_url`.
El cuerpo del PUT es el archivo binario; una cadena Base64 enviada como texto no
se convierte automáticamente en un documento. Por ejemplo, en Node.js:

<CodeGroup>
  ```bash cURL theme={"dark"}
  # Replace this value with the complete item_options.upload_url.
  UPLOAD_URL="https://files.gotrebol.com/uploads/ITEM_ID_original_file?SIGNED_PARAMETERS"
  # Replace document.b64 with your file containing only the Base64 string.
  openssl base64 -d -A -in document.b64 | curl --fail-with-body -X PUT "$UPLOAD_URL" \
    -H "Content-Type: application/pdf" \
    --data-binary @-
  ```

  ```javascript Node.js theme={"dark"}
  // Replace this value with the complete item_options.upload_url.
  const uploadUrl = "https://files.gotrebol.com/uploads/ITEM_ID_original_file?SIGNED_PARAMETERS";
  // Replace this value with the complete Base64 document, without a data URI prefix.
  const documentBase64 = "YOUR_DOCUMENT_BASE64";
  const response = await fetch(uploadUrl, {
    method: "PUT",
    headers: { "Content-Type": "application/pdf" },
    body: Buffer.from(documentBase64, "base64"),
  });
  if (!response.ok) throw new Error(`Upload failed: ${response.status}`);
  ```
</CodeGroup>

`documentBase64` debe contener solamente el contenido codificado, sin el prefijo
`data:application/pdf;base64,`. Confirma la carga únicamente después de un PUT
exitoso. Usa el mismo formato y límites de archivo que en el flujo habitual.

***

## Paso 3: Confirmar y procesar el archivo

Una vez que el archivo se ha subido, debes notificar a Trébol que el documento está listo para ser procesado. Esto se hace enviando una solicitud `PUT` al endpoint del `item` específico, usando su `id`.

**Endpoint:** `PUT /verification-items/{item_id}`

<Note>
  Usa el valor de `items[].id` recibido al crear la verificación, o el `id`
  del item del arreglo devuelto por add-items.
</Note>

**Body:**

```json theme={"dark"}
{
  "options": {
    "uploaded_file": true
  }
}
```

<CodeGroup>
  ```bash cURL theme={"dark"}
  # Replace YOUR_API_KEY and ITEM_ID with your API key and the returned item id.
  curl --fail-with-body -X PUT "https://api.gotrebol.com/verification-items/ITEM_ID" \
    -H "x-api-key: YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    --data '{"options":{"uploaded_file":true}}'
  ```

  ```javascript Node.js theme={"dark"}
  // Replace these values with your API key and the returned item id.
  const apiKey = "YOUR_API_KEY";
  const itemId = "ITEM_ID";
  const response = await fetch(`https://api.gotrebol.com/verification-items/${itemId}`, {
    method: "PUT",
    headers: { "x-api-key": apiKey, "Content-Type": "application/json" },
    body: JSON.stringify({ options: { uploaded_file: true } }),
  });
  if (!response.ok) throw new Error(`Confirmation failed: ${response.status}`);
  console.log(await response.json());
  ```
</CodeGroup>

La respuesta `200` contiene el item y el indicador de procesamiento:

```json theme={"dark"}
{
  "item": {
    "id": 29639,
    "item_type": "doc_validation",
    "item_status": "pending"
  },
  "triggeredSideEffects": true
}
```

La API verifica que el archivo exista y solicita el procesamiento correspondiente
al tipo del item: clasificación, validación, extracción o separación. La respuesta
incluye `item` y `triggeredSideEffects: true`; el procesamiento es asíncrono y el
item puede seguir en `pending` al responder. Consulta su estado o espera los
[webhooks de Trébol](/docs/guia-devs/webhooks) para conocer el resultado.

Si el archivo todavía no existe, la confirmación devuelve `404` con el mensaje
`S3 object not found` y no inicia el procesamiento. La confirmación comprueba la
existencia del objeto; la validación del contenido ocurre durante el procesamiento.
Tras ese `404`, sube el archivo y vuelve a confirmar. Si la URL expiró, consulta
el item para obtener una URL nueva antes de repetir el PUT del archivo.

Repite los pasos 2 y 3 para cada item que requiera una carga directa.
