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

# Exportações e disputas

> Execute jobs de exportação assíncronos para gerar relatórios de reconciliação para download e abra, comprove e resolva disputas contra exceções.

Este guia aborda dois fluxos de trabalho de operador que terminam em um artefato para download ou resolvido: **jobs de exportação** (enfileire um relatório, consulte seu status até que ele seja concluído e baixe o arquivo) e **disputas** (abra uma disputa contra uma exceção, anexe evidências e depois encerre-a como ganha ou perdida). Ambos são delimitados por tenant a partir do JWT.

## Jobs de exportação

***

As exportações são assíncronas. Você cria um job delimitado a um contexto, consulta seu status por ID e baixa o arquivo assim que ele atinge `SUCCEEDED`. Os status são `QUEUED`, `RUNNING`, `SUCCEEDED`, `FAILED`, `EXPIRED` e `CANCELED`.

### Criar um job de exportação

`POST` para a coleção export-jobs do contexto. Responde `202 Accepted` com o ID do job e uma 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` — um de `MATCHED`, `UNMATCHED`, `VARIANCE`, `EXCEPTIONS` (os aliases `MATCHES` e `UNMATCHED_TRANSACTIONS` são normalizados).
* `format` — `CSV`, `JSON` ou `XML` (normalizado para maiúsculas).
* `dateFrom` / `dateTo` — `YYYY-MM-DD` opcional; `dateFrom` assume por padrão 30 dias antes de `dateTo`, e `dateTo` assume por padrão amanhã (UTC).
* `sourceId` — filtro de fonte opcional.

<Note>`SUMMARY` e `PDF` **não** são suportados para jobs de exportação assíncronos e são rejeitados com `400`. A janela de datas também tem um limite máximo de intervalo (uma requisição fora do intervalo é rejeitada em vez de ser silenciosamente ajustada).</Note>

### Consultar o status do job

Leia a rota de nível superior do job (a `statusUrl` da criação).

```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 apenas quando `status` é `FAILED`; `downloadUrl` aparece somente depois que o job atinge `SUCCEEDED` e o arquivo ainda está disponível. Você pode listar os jobs de um contexto com `GET /v1/contexts/{contextId}/export-jobs`, listar todos os jobs com `GET /v1/export-jobs` e cancelar um job enfileirado ou em execução com `POST /v1/export-jobs/{jobId}/cancel`.

### Baixar o arquivo

Retorna uma URL pré-assinada, o nome de arquivo original, um checksum SHA-256 e o tempo de vida restante da URL em 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>Os arquivos de exportação são removidos após `expiresAt` (7 dias por padrão). Assim que um job está `EXPIRED`, o arquivo não pode mais ser baixado — execute a exportação novamente para regenerá-lo.</Warning>

## Disputas

***

Uma disputa é aberta contra uma **exceção** específica quando uma divergência de reconciliação precisa ser contestada. Seu ciclo de vida é `DRAFT` → `OPEN` → `PENDING_EVIDENCE` → `WON` / `LOST`.

### Abrir uma disputa

`POST` para a coleção disputes da exceção.

```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` é um de `BANK_FEE_ERROR`, `UNRECOGNIZED_CHARGE`, `DUPLICATE_TRANSACTION` ou `OTHER`. O principal que abre a disputa é registrado em `openedBy`.

### Enviar evidência por URL

Anexe uma referência a um arquivo de evidência já hospedado mais um comentário descritivo.

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

### Fazer upload de um arquivo de evidência

Transmita os bytes brutos do arquivo diretamente para o armazenamento de objetos delimitado por tenant — o comentário viaja como parâmetro de consulta e o arquivo como corpo da requisição. Responde `201 Created` com a disputa atualizada. Os tipos de conteúdo permitidos são `application/pdf`, `image/png`, `image/jpeg` e `text/csv`; o corpo tem um limite 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
```

Cada item de evidência armazenado é retornado no array `evidence` da disputa:

```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>O endpoint de upload falha de forma segura com `503` quando o armazenamento de objetos não está configurado, rejeita corpos de tamanho excessivo com `413` e rejeita tipos de conteúdo fora da lista de permitidos com `415`. O tenant e a disputa são sempre resolvidos a partir do JWT e do caminho — nunca a partir do corpo.</Note>

### Encerrar uma disputa

Registre o resultado. `won` define o estado terminal como `WON` ou `LOST`, com uma nota `resolution` obrigatória.

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

Você pode listar disputas com `GET /v1/disputes` (filtre por `state`, `category`, intervalo de datas; ordene e pagine por cursor) e obter uma com `GET /v1/disputes/{disputeId}`.

## Códigos de resposta

***

| Status | Significado                                                                                                  |
| ------ | ------------------------------------------------------------------------------------------------------------ |
| `200`  | Dados de exportação/disputa retornados                                                                       |
| `201`  | Arquivo de evidência enviado                                                                                 |
| `202`  | Job de exportação aceito                                                                                     |
| `400`  | Entrada inválida (tipo/formato de relatório não suportado, intervalo de datas incorreto, categoria inválida) |
| `404`  | Contexto, job de exportação, exceção ou disputa não encontrados                                              |
| `409`  | Transição de estado de disputa inválida                                                                      |
| `413`  | O arquivo de evidência excede o limite de 10 MiB                                                             |
| `415`  | Tipo de conteúdo de evidência não está na lista de permitidos                                                |
| `422`  | Campo malformado                                                                                             |
| `503`  | Armazenamento de exportação ou evidência não configurado                                                     |
