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

# Exportaciones y disputas

> Ejecuta trabajos de exportación asíncronos para generar informes de conciliación descargables, y abre, respalda con evidencia y resuelve disputas contra excepciones.

Esta guía cubre dos workflows del operador que terminan en un artefacto descargable o resuelto. Con los **trabajos de exportación**, pones un informe en cola, consultas su estado hasta que se complete y descargas el archivo. Con las **disputas**, abres una disputa contra una excepción, adjuntas evidencia y luego la cierras como ganada o perdida. Ambos están delimitados por tenant a partir del JWT.

## Trabajos de exportación

***

Las exportaciones son asíncronas. Creas un trabajo delimitado a un contexto, consultas su estado por ID y descargas el archivo una vez que alcanza `SUCCEEDED`. Los estados son `QUEUED`, `RUNNING`, `SUCCEEDED`, `FAILED`, `EXPIRED` y `CANCELED`.

### Crea un trabajo de exportación

`POST` a la colección export-jobs del contexto. Responde `202 Accepted` con el ID del trabajo y una URL de consulta.

```bash theme={null}
curl -X POST "https://api.matcher.example.com/v1/contexts/{contextId}/export-jobs" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "reportType": "MATCHED",
    "format": "CSV",
    "dateFrom": "2025-01-01",
    "dateTo": "2025-01-31",
    "sourceId": "550e8400-e29b-41d4-a716-446655440000"
  }'
```

```json theme={null}
{
  "jobId": "550e8400-e29b-41d4-a716-446655440000",
  "status": "QUEUED",
  "statusUrl": "/v1/export-jobs/550e8400-e29b-41d4-a716-446655440001"
}
```

* `reportType`: uno de `MATCHED`, `UNMATCHED`, `VARIANCE`, `EXCEPTIONS` (los alias `MATCHES` y `UNMATCHED_TRANSACTIONS` se normalizan a estos valores).
* `format`: `CSV`, `JSON` o `XML` (normalizado a mayúsculas).
* `dateFrom` / `dateTo`: `YYYY-MM-DD` opcional. `dateFrom` toma por defecto 30 días antes de `dateTo`, y `dateTo` toma por defecto mañana (UTC).
* `sourceId`: filtro de fuente opcional.

<Note>Los trabajos de exportación asíncronos **no** admiten `SUMMARY` ni `PDF`. Una solicitud de cualquiera de los dos devuelve `400`. La ventana de fechas también tiene un intervalo máximo. Una solicitud que exceda el rango devuelve un error en lugar de recortar la ventana silenciosamente.</Note>

### Consulta el estado del trabajo

Lee la ruta de nivel superior del trabajo (el `statusUrl` de la creación).

```bash theme={null}
curl -X GET "https://api.matcher.example.com/v1/export-jobs/{jobId}" \
  -H "Authorization: Bearer $TOKEN"
```

```json theme={null}
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "reportType": "MATCHED",
  "format": "CSV",
  "status": "SUCCEEDED",
  "recordsWritten": 4250,
  "bytesWritten": 524288,
  "fileName": "matched_report_2025-01-31.csv",
  "createdAt": "2025-01-15T10:30:00Z",
  "startedAt": "2025-01-15T10:30:05Z",
  "finishedAt": "2025-01-15T10:35:00Z",
  "expiresAt": "2025-01-16T10:30:00Z",
  "downloadUrl": "https://storage.example.com/exports/matched_report.csv?token=abc"
}
```

`error` está presente solo cuando `status` es `FAILED`. `downloadUrl` aparece solo una vez que el trabajo alcanzó `SUCCEEDED` y el archivo sigue disponible. Puedes listar los trabajos de un contexto con `GET /v1/contexts/{contextId}/export-jobs`, listar todos los trabajos con `GET /v1/export-jobs`, y cancelar un trabajo en cola o en ejecución con `POST /v1/export-jobs/{jobId}/cancel`.

### Descarga el archivo

Devuelve una URL prefirmada, el nombre del archivo original, una suma de verificación SHA-256 y el tiempo de vida restante de la URL en segundos.

```bash theme={null}
curl -X GET "https://api.matcher.example.com/v1/export-jobs/{jobId}/download" \
  -H "Authorization: Bearer $TOKEN"
```

```json theme={null}
{
  "downloadUrl": "https://storage.example.com/exports/report.csv?token=abc",
  "fileName": "matched_report.csv",
  "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
  "expiresIn": 3600
}
```

<Warning>Los archivos de exportación se purgan después de `expiresAt` (7 días de forma predeterminada). Una vez que un trabajo está en `EXPIRED`, el archivo ya no se puede descargar. Vuelve a ejecutar la exportación para regenerarlo.</Warning>

## Disputas

***

Abres una disputa contra una **excepción** específica cuando necesitas impugnar una discrepancia de conciliación. Su ciclo de vida empieza en `DRAFT` → `OPEN`. Desde `OPEN`, una disputa puede pasar a `PENDING_EVIDENCE` (y volver a `OPEN`) o cerrarse directamente como `WON` / `LOST`. Solo `WON` es terminal. Puedes reabrir una disputa `LOST` a `OPEN`.

### Abre una disputa

`POST` a la colección de disputas de la excepción.

```bash theme={null}
curl -X POST "https://api.matcher.example.com/v1/exceptions/{exceptionId}/disputes" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "category": "BANK_FEE_ERROR",
    "description": "Transaction amount differs from invoice"
  }'
```

```json theme={null}
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "exceptionId": "550e8400-e29b-41d4-a716-446655440001",
  "category": "BANK_FEE_ERROR",
  "state": "OPEN",
  "description": "Transaction amount differs from invoice",
  "openedBy": "user@example.com",
  "evidence": [],
  "createdAt": "2025-01-15T10:30:00Z",
  "updatedAt": "2025-01-15T10:30:00Z"
}
```

`category` es uno de `BANK_FEE_ERROR`, `UNRECOGNIZED_CHARGE`, `DUPLICATE_TRANSACTION` o `OTHER`. El campo `openedBy` registra el principal que la abrió.

### Envía evidencia por URL

Adjunta una referencia a un archivo de evidencia ya alojado, junto con un comentario descriptivo.

```bash theme={null}
curl -X POST "https://api.matcher.example.com/v1/disputes/{disputeId}/evidence" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "comment": "Attached bank statement showing correct amount",
    "fileUrl": "https://storage.example.com/evidence/doc123.pdf"
  }'
```

### Sube un archivo de evidencia

Transmite los bytes del archivo sin procesar directamente al almacenamiento de objetos delimitado por tenant. El comentario viaja como parámetro de consulta y el archivo como cuerpo de la solicitud. Responde `201 Created` con la disputa actualizada. Los tipos de contenido permitidos son `application/pdf`, `image/png`, `image/jpeg` y `text/csv`. El cuerpo tiene un límite de 10 MiB.

```bash theme={null}
curl -X POST "https://api.matcher.example.com/v1/disputes/{disputeId}/evidence/upload?comment=Bank%20statement%20showing%20correct%20amount" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/pdf" \
  --data-binary @statement.pdf
```

El arreglo `evidence` de la disputa lista cada elemento de evidencia almacenado:

```json theme={null}
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "disputeId": "550e8400-e29b-41d4-a716-446655440001",
  "comment": "Bank statement showing correct amount",
  "submittedBy": "user@example.com",
  "fileUrl": "https://storage.example.com/evidence/doc123.pdf",
  "submittedAt": "2025-01-15T10:30:00Z"
}
```

<Note>
  El endpoint de carga falla de forma cerrada con `503` cuando no configuras el almacenamiento de objetos. Rechaza los cuerpos con exceso de tamaño con `413` y los tipos de contenido fuera de la lista permitida con `415`. El tenant siempre proviene del JWT y la disputa de la ruta, nunca del cuerpo.
</Note>

### Cierra una disputa

Registra el resultado. `won` establece el estado en `WON` (terminal) o `LOST` (reabrible), con una nota `resolution` obligatoria.

```bash theme={null}
curl -X POST "https://api.matcher.example.com/v1/disputes/{disputeId}/close" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "won": true,
    "resolution": "Counterparty acknowledged the error and issued correction"
  }'
```

Puedes listar disputas con `GET /v1/disputes` y obtener una con `GET /v1/disputes/{disputeId}`. El endpoint de listado filtra por `state`, `category` y rango de fechas, y admite ordenamiento y paginación por cursor.

## Códigos de respuesta

***

| Estado | Significado                                                                                              |
| ------ | -------------------------------------------------------------------------------------------------------- |
| `200`  | Datos de exportación o disputa devueltos                                                                 |
| `201`  | Archivo de evidencia cargado                                                                             |
| `202`  | Trabajo de exportación aceptado                                                                          |
| `400`  | Entrada inválida (tipo de informe o formato no admitido, rango de fechas incorrecto, categoría inválida) |
| `404`  | Contexto, trabajo de exportación, excepción o disputa no encontrados                                     |
| `409`  | Transición de estado de disputa inválida                                                                 |
| `413`  | El archivo de evidencia supera el límite de 10 MiB                                                       |
| `415`  | Tipo de contenido de evidencia fuera de la lista permitida                                               |
| `422`  | Campo con formato incorrecto                                                                             |
| `503`  | Almacenamiento de exportación o evidencia no configurado                                                 |
