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

# Exportaciones

> Obtén el conjunto de datos completo y filtrado como descarga CSV o JSONL, generado como trabajo asíncrono.

Las listas paginan de a máximo 100 filas por solicitud, lo cual es correcto
para una app y equivocado para una carga de BI. Las **exportaciones** producen
un archivo con el conjunto de datos completo y filtrado de una entidad
(procesos, actuaciones o demandados), hasta 100.000 filas, y te entregan una
URL de descarga.

```
POST https://api.legal.usecroma.com/v1/exports
```

Como un portafolio grande tarda más de lo que una sola solicitud debería
esperar, una exportación corre como **trabajo asíncrono**: la misma solicitud
puede resolverse de tres maneras, y tú eliges cuál le conviene a tu app.

<Note>
  **Las exportaciones pequeñas se sienten síncronas.** Por defecto la solicitud
  espera hasta 20 segundos y, si el archivo está listo, devuelve
  `200 { data }` con la URL. Los otros modos son opcionales, para cuando
  prefieras no mantener la conexión abierta.
</Note>

## La solicitud

```json theme={"dark"}
{
  "entity": "processes",
  "format": "csv",
  "filters": { "status": "TRACKING", "date_from": "2024-01-01" }
}
```

| Campo          | Obligatorio | Significado                                                                                                                                                                                                                        |
| -------------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `entity`       | sí          | `processes`, `actions` o `defendants`.                                                                                                                                                                                             |
| `format`       | no          | `csv` (por defecto; UTF-8 con BOM para que Excel muestre las tildes) o `jsonl` (un objeto JSON por línea, ideal para scripts).                                                                                                     |
| `filters`      | no          | Los mismos nombres que los parámetros de consulta de los endpoints de lista, en un solo objeto plano. Los filtros que no aplican a la entidad elegida se ignoran. Consulta [ExportFilters](/es/legal/api-reference/create-export). |
| `callback_url` | no          | URL HTTPS pública a la que hacer `POST` con el resultado. Activa el [modo callback](#modo-3-callback-webhook).                                                                                                                     |

Los campos desconocidos en el cuerpo (o dentro de `filters`) se rechazan con `400`.

El resultado, una vez existe el archivo:

```json theme={"dark"}
{
  "data": {
    "url": "https://files.usecroma.com/legal-exports/processes-2026-08-21.csv",
    "entity": "processes",
    "format": "csv",
    "rows": 1280,
    "bytes": 418233,
    "truncated": false,
    "expires_at": "2026-08-22T14:03:10.000Z"
  }
}
```

* `url` es imposible de adivinar pero no está autenticada: cualquiera que la
  tenga puede descargar el archivo. Está garantizada hasta `expires_at` (24
  horas después de completarse) y se elimina poco después; descárgala pronto y
  no la publiques en ningún lugar público.
* `truncated: true` significa que se alcanzó el tope de 100.000 filas y el
  archivo **no** es el conjunto completo. Acota los filtros (por ejemplo por
  rango de fechas) y exporta de nuevo.

## Las tres formas de obtener el resultado

| Modo                               | Envías                         | Recibes                                                  |
| ---------------------------------- | ------------------------------ | -------------------------------------------------------- |
| **Esperar en línea** (por defecto) | nada extra, o `Prefer: wait=N` | `200 { data }` si termina a tiempo; si no, `202`         |
| **Polling**                        | `Prefer: wait=0`               | `202` de inmediato, luego `GET /jobs/:id` hasta terminar |
| **Callback**                       | `callback_url` en el cuerpo    | `202` de inmediato, luego un `POST` a tu URL al terminar |

Los tres están respaldados por el **mismo trabajo**, así que elige por
solicitud.

***

## Modo 1: Esperar en línea (por defecto)

Solo llama al endpoint. La solicitud se mantiene abierta hasta que el archivo
está listo (hasta **20 segundos** por defecto) y devuelve `{ data }`.

<CodeGroup>
  ```bash cURL theme={"dark"}
  curl -X POST https://api.legal.usecroma.com/v1/exports \
    -H "Authorization: Bearer $CROMA_LEGAL_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{ "entity": "defendants", "format": "jsonl" }'
  ```

  ```ts TypeScript theme={"dark"}
  const res = await fetch("https://api.legal.usecroma.com/v1/exports", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.CROMA_LEGAL_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ entity: "defendants", format: "jsonl" }),
  });

  if (res.status === 200) {
    const { data } = await res.json(); // data.url está lista para descargar
  } else if (res.status === 202) {
    // no estuvo lista a tiempo; consulta la URL de estado (ver Modo 2)
  }
  ```
</CodeGroup>

Controla cuánto esperar con el encabezado estándar
[`Prefer: wait=N`](https://www.rfc-editor.org/rfc/rfc7240#section-4.3)
(segundos, con tope en **55**):

```bash theme={"dark"}
curl -X POST https://api.legal.usecroma.com/v1/exports \
  -H "Authorization: Bearer $CROMA_LEGAL_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Prefer: wait=50" \
  -d '{ "entity": "processes", "format": "csv" }'
```

* **`200`**: listo. El cuerpo es `{ "data": … }` como arriba.
* **`202`**: no terminó dentro de la espera. El cuerpo es un
  [sobre de trabajo](#el-sobre-del-trabajo); sigue su `status_url` para hacer
  polling. El encabezado `X-Job-Id` trae el id del trabajo.

<Note>
  Maneja siempre tanto `200` como `202`. Un `202` no es un error; solo
  significa "todavía generando, vuelve por el resultado". Un portafolio con
  decenas de miles de actuaciones normalmente tarda más que los 20 segundos de
  espera por defecto.
</Note>

***

## Modo 2: Polling

Envía `Prefer: wait=0` para recibir un `202` de inmediato y luego haz `GET` al
`status_url` del trabajo hasta que llegue a un estado terminal.

<CodeGroup>
  ```bash cURL theme={"dark"}
  # 1. Inicia la exportación (devuelve 202 de inmediato)
  curl -i -X POST https://api.legal.usecroma.com/v1/exports \
    -H "Authorization: Bearer $CROMA_LEGAL_API_KEY" \
    -H "Content-Type: application/json" \
    -H "Prefer: wait=0" \
    -d '{ "entity": "actions", "filters": { "since": "2026-01-01" } }'

  # 2. Consulta el status_url de la respuesta (o el encabezado Location)
  curl https://api.legal.usecroma.com/jobs/run_abc123def456 \
    -H "Authorization: Bearer $CROMA_LEGAL_API_KEY"
  ```

  ```ts TypeScript theme={"dark"}
  // 1. Inicia la exportación
  const start = await fetch("https://api.legal.usecroma.com/v1/exports", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.CROMA_LEGAL_API_KEY}`,
      "Content-Type": "application/json",
      Prefer: "wait=0",
    },
    body: JSON.stringify({ entity: "actions", filters: { since: "2026-01-01" } }),
  });
  const { job } = await start.json();

  // 2. Haz polling hasta un estado terminal
  async function poll(statusUrl: string) {
    while (true) {
      const res = await fetch(statusUrl, {
        headers: { Authorization: `Bearer ${process.env.CROMA_LEGAL_API_KEY}` },
      });
      const body = await res.json();
      if (body.job.status === "completed") return body.data;
      if (["failed", "canceled", "expired"].includes(body.job.status)) {
        throw new Error(body.error?.message ?? body.job.status);
      }
      // respeta Retry-After; por defecto 2 s mientras corre
      const wait = Number(res.headers.get("Retry-After") ?? 2) * 1000;
      await new Promise((r) => setTimeout(r, wait));
    }
  }

  const { url } = await poll(job.status_url);
  ```
</CodeGroup>

`GET /jobs/:id` siempre devuelve `200` con el [sobre](#el-sobre-del-trabajo).
Mientras el trabajo sigue corriendo incluye un encabezado `Retry-After`
(segundos); úsalo para marcar el ritmo del polling. El polling tiene su propia
[cuota generosa](/es/legal/rate-limits). Los trabajos están limitados a tu
organización; un trabajo de otra organización se lee como `404`.

***

## Modo 3: Callback (webhook)

Incluye un `callback_url` en el cuerpo de la solicitud. Recibes un `202` de
inmediato y Croma hace `POST` con el resultado a tu URL cuando el archivo está
listo, sin polling.

```bash theme={"dark"}
curl -i -X POST https://api.legal.usecroma.com/v1/exports \
  -H "Authorization: Bearer $CROMA_LEGAL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
        "entity": "processes",
        "format": "csv",
        "callback_url": "https://tu-app.com/webhooks/croma-legal"
      }'
```

`callback_url` debe ser una URL **HTTPS** absoluta en un host público
(localhost y los rangos privados se rechazan). Cuando el trabajo termina, Croma
envía un `POST`:

* **Cuerpo**: el mismo [sobre de trabajo](#el-sobre-del-trabajo) del endpoint
  de polling.
* **`x-croma-job-id`**: el id del trabajo.
* **`x-croma-signature`**: `sha256=<hmac>`, un HMAC-SHA256 del cuerpo crudo de
  la solicitud, para que verifiques la integridad de la carga.

```http theme={"dark"}
POST /webhooks/croma-legal HTTP/1.1
content-type: application/json
x-croma-job-id: run_abc123def456
x-croma-signature: sha256=9f86d081…

{ "job": { "id": "run_abc123def456", "status": "completed", … }, "data": { "url": "…" }, "error": null }
```

<Note>
  La verificación de la firma usa un secreto compartido emitido por Croma;
  contáctanos si quieres habilitarla para tus callbacks. Responde `2xx`
  rápido; las respuestas distintas de `2xx` se reintentan.
</Note>

***

## El sobre del trabajo

La respuesta `202`, `GET /jobs/:id` y el cuerpo del callback comparten una
misma forma:

```json theme={"dark"}
{
  "job": {
    "id": "run_abc123def456",
    "status": "completed",
    "endpoint": "/v1/exports",
    "created_at": "2026-08-21T14:03:10.000Z",
    "finished_at": "2026-08-21T14:03:41.000Z",
    "status_url": "https://api.legal.usecroma.com/jobs/run_abc123def456"
  },
  "data": { "url": "…", "entity": "processes", "format": "csv", "rows": 1280, "bytes": 418233, "truncated": false, "expires_at": "2026-08-22T14:03:41.000Z" },
  "error": null
}
```

* **`data`** solo viene poblado cuando `status` es `completed`. Si no, es
  `null`.
* **`error`** solo viene poblado cuando el trabajo está en `failed`, como
  `{ "type", "code", "message" }` con `code: "job_failed"`.

### Estados

| `status`    | ¿Terminal? | Significado                                         |
| ----------- | ---------- | --------------------------------------------------- |
| `queued`    | no         | Aceptado, esperando para correr.                    |
| `running`   | no         | Generando el archivo.                               |
| `completed` | sí         | Listo. Lee `data.url`.                              |
| `failed`    | sí         | La exportación falló. Lee `error`; créala de nuevo. |
| `canceled`  | sí         | La ejecución fue cancelada.                         |
| `expired`   | sí         | La ejecución expiró antes de completarse.           |

## Qué trae el archivo

Las columnas son las mismas elijas `csv` o `jsonl`. Los valores anidados
(`metadata`) se serializan como texto JSON en las celdas del CSV.

<Tabs>
  <Tab title="processes">
    `id`, `registration_number`, `plaintiff_name`, `defendant_name`,
    `defendant_id`, `office`, `status`, `registration_date`,
    `last_discovery_date`, `is_private`, `latest_action_message`,
    `latest_action_date`, `metadata`.

    Las dos columnas `latest_action_*` traen la actuación más reciente de cada
    proceso, así que el archivo se lee como la vista de portafolio del
    dashboard.
  </Tab>

  <Tab title="actions">
    `id`, `process_id`, `registration_number`, `message`, `note`,
    `registration_date`, `action_created_at`, `source`, `publication_url`,
    `document_url`, `plaintiff_name`, `defendant_name`, `defendant_id`,
    `defender_name`, `office`, `priority`, `is_private`,
    `last_discovery_date`, `metadata`.

    Es el conjunto más grande: filtra por `since`, `date_from` / `date_to`,
    `office` o `defendant` para mantenerte bajo el tope de filas.
  </Tab>

  <Tab title="defendants">
    `id`, `identification_number`, `name`, `process_count`, `metadata`,
    `created_at`.
  </Tab>
</Tabs>

## Referencia de encabezados

| Encabezado                   | Dónde                    | Significado                                                                                                         |
| ---------------------------- | ------------------------ | ------------------------------------------------------------------------------------------------------------------- |
| `Prefer: wait=N`             | solicitud                | Segundos a esperar en línea antes de devolver `202`. Por defecto 20, tope 55. `wait=0` devuelve `202` de inmediato. |
| `Preference-Applied: wait=N` | respuesta `200`          | Repite la espera que se aplicó.                                                                                     |
| `Location`                   | respuesta `202`          | El `status_url` del trabajo.                                                                                        |
| `Retry-After`                | `202` / polling en curso | Segundos sugeridos antes de volver a consultar.                                                                     |
| `X-Job-Id`                   | respuesta `202` / `200`  | El id del trabajo.                                                                                                  |

<CardGroup cols={2}>
  <Card title="POST /v1/exports" icon="code" href="/es/legal/api-reference/create-export">
    Esquema completo de solicitud y respuesta, con los filtros por entidad.
  </Card>

  <Card title="Errores" icon="triangle-exclamation" href="/es/legal/errors">
    Cómo funcionan las fallas y el objeto `error`.
  </Card>
</CardGroup>
