---
url: https://developers.zarv.com/api/lens.md
description: >-
  O Lens organiza a investigação de sinistro em três etapas — Coleta, Análise e
  Investigação — com leitura de documentos por IA, nove dimensões de cruzamento
  e quadro kanban.
---

# Lens

O **Lens** organiza a investigação de um sinistro de ponta a ponta: recebe os documentos do caso, lê cada um com um agente de IA, monta o caso a partir do que leu, cruza tudo em nove dimensões e entrega ao analista um veredito por dimensão — com os alertas que o sustentam e a evidência de cada alerta.

O trabalho acontece em três etapas, e é assim que esta documentação está organizada:

| Etapa                                      | O que acontece                                                                                                    |
| ------------------------------------------ | ----------------------------------------------------------------------------------------------------------------- |
| **[Coleta](/api/lens/coleta)**             | Abrir o caso, declarar os envolvidos e enviar os documentos. O Lens identifica, lê e monta o caso a partir deles. |
| **[Análise](/api/lens/analise)**           | Rodar as nove dimensões sobre o que foi coletado e receber um veredito por dimensão, com alertas e evidências.    |
| **[Investigação](/api/lens/investigacao)** | Responder aos alertas com nova evidência, incluir quem a apuração revelou, reanalisar e dar o desfecho ao caso.   |

Atravessando as três, o **[Quadro](/api/lens/quadro)**: cada caso ocupa uma raia, e o Lens o move sozinho a cada acontecimento.

## O modelo

Tudo gira em torno de um **caso** (`research`), que tem dois tipos de filho:

* **Envolvidos** (`entity`) — uma pessoa, uma empresa ou um veículo. O veículo é raiz; as pessoas e as empresas se ligam a ele. Cada um tem papéis no caso (`SEGURADO`, `MOTORISTA`, `PRINCIPAL`, `FUNILARIA`…), e a mesma pessoa pode ter mais de um: o segurado que dirigia é `SEGURADO` **e** `MOTORISTA`.
* **Documentos** (`document`) — o boletim de ocorrência, a apólice, o aviso de sinistro, o termo de terceiro, a CNH, o CRLV, as fotos do veículo e do local.

Um caso é **por envolvido**: a pessoa e o veículo dela entram juntos, e o primeiro envolvido é o segurado.

## Rotas

Todas em `https://services.zarv.com`, com token Bearer JWT.

| Rota                                                             | O que faz                                   | Etapa                  |
| ---------------------------------------------------------------- | ------------------------------------------- | ---------------------- |
| `POST /api/v1/lens/{workspaceId}/research`                       | Abre um caso                                | Coleta                 |
| `GET /api/v1/lens/{workspaceId}/research`                        | Lista os casos do workspace (e de uma raia) | Coleta                 |
| `GET /api/v1/lens/{workspaceId}/{userId}/research`               | Lista os casos de um usuário                | Coleta                 |
| `GET /api/v1/lens/{workspaceId}/research/{id}`                   | Consulta o caso, o envio e a análise        | Coleta · Análise       |
| `PUT /api/v1/lens/{workspaceId}/research/{id}`                   | Edita o caso e o move no quadro             | Coleta · Investigação  |
| `DELETE /api/v1/lens/{workspaceId}/research/{id}`                | Apaga o caso                                | Coleta                 |
| `POST /api/v1/lens/{workspaceId}/research/{researchId}/document` | Envia os documentos do caso (em lote)       | Coleta · Investigação  |
| `GET /api/v1/lens/{workspaceId}/research/{researchId}/document`  | Lista os documentos (`?content=false`)      | Coleta                 |
| `GET · PUT · DELETE .../document/{id}`                           | Consulta, substitui e apaga um documento    | Coleta                 |
| `POST /api/v1/lens/{workspaceId}/research/{researchId}/entity`   | Inclui um envolvido                         | Coleta · Investigação  |
| `GET /api/v1/lens/{workspaceId}/research/{researchId}/entity`    | Lista os envolvidos                         | Coleta                 |
| `GET · PUT · DELETE .../entity/{id}`                             | Consulta, edita e remove um envolvido       | Coleta · Investigação  |
| `POST /api/v1/lens/{workspaceId}/research/{researchId}/analyze`  | Pede a análise do caso                      | Análise · Investigação |
| `GET /api/v1/lens/{workspaceId}/kanban`                          | Lista as raias do quadro                    | Quadro                 |
| `GET /api/v1/lens/{workspaceId}/kanban/{id}`                     | Consulta uma raia                           | Quadro                 |
| `GET /api/lens/health`                                           | Saúde do serviço (sem autenticação)         | —                      |

A referência completa, com todos os campos e exemplos, está em [Referência da API](/api/lens/reference), e o spec cru em [`/openapi/lens-api.json`](/openapi/lens-api.json).

## O caminho de um caso

```
1. POST   .../research                     abre o caso          → raia Abertura
2. POST   .../research/{id}/document       envia os arquivos    → 202, worker lê e monta
3. GET    .../research/{id}                acompanha o envio    → documents.status: DONE
                                                                → raia Pronto para análise
4. POST   .../research/{id}/analyze        pede a análise       → 202, raia Analisando
5. GET    .../research/{id}                lê o resultado       → analysis.result
                                                                → raia Analisado
6. POST   .../research/{id}/document       anexa a diligência   (Investigação)
   POST   .../research/{id}/analyze        reanalisa
7. PUT    .../research/{id}                move para o desfecho → raia Aprovado ou Reprovado
```

## As rotas assíncronas

Duas operações do Lens levam minutos — ler 40 arquivos com agentes de IA e rodar nove dimensões sobre o caso — e nenhuma delas cabe no tempo de uma requisição HTTP. As duas respondem **`202 Accepted`** na hora e um worker trabalha depois:

| Rota                | Resposta imediata          | Onde acompanhar              |
| ------------------- | -------------------------- | ---------------------------- |
| `POST .../document` | `202` com `status: QUEUED` | `documents` no `GET` do caso |
| `POST .../analyze`  | `202` com `status: QUEUED` | `analysis` no `GET` do caso  |

Os dois seguem a mesma máquina de estados:

```
(sem job) ──pedido──▶ QUEUED ──worker pega──▶ PROCESSING ──▶ DONE | FAILED
```

Consulte o caso a cada poucos segundos até o `status` ser terminal. O envio dos documentos ainda traz `progress`, de 0 a 100, para você mostrar uma barra de verdade — e `results`, que cresce arquivo a arquivo: um arquivo pronto já aparece lá antes de o envio terminar.

Um job que derruba o worker três vezes termina `FAILED` com `errorCode: ATTEMPTS_EXHAUSTED`, em vez de travar a vaga para sempre.

::: warning Uma coisa de cada vez
Há **um envio** e **uma análise** por caso. Pedir um segundo envio, ou uma segunda análise, enquanto o primeiro roda é `409`. Pedir a análise com o envio rodando também é `409`: a análise lê o caso que o envio ainda está gravando.

Enquanto um dos dois roda, mover o caso de raia também é `409` — naquele momento, o caso é do worker.
:::

## Idempotência

A abertura do caso aceita o header **`Idempotency-Key`** (um UUID por caso, por exemplo). Com ele, repetir a requisição depois de um timeout de rede devolve o caso que já existe, com `200` e o header `Idempotent-Replayed: true`, em vez de abrir um segundo. A mesma chave com um corpo diferente responde `409 IDEMPOTENCY_KEY_REUSED`.

Sem a chave, duas chamadas abrem dois casos: o Lens nunca deduplica por conteúdo.

## Erros

Toda recusa tem o mesmo corpo:

```json
{ "error": "research not found" }
```

`error` é a frase de diagnóstico e pode mudar. Quando a recusa tem um **código estável**, decida por ele:

| HTTP  | `code`                                  | Quando                                                                                      |
| ----- | --------------------------------------- | ------------------------------------------------------------------------------------------- |
| `400` | `IDENTITY_IS_IMMUTABLE`                 | Tentou trocar a placa ou o CPF/CNPJ de um envolvido                                         |
| `400` | `RESEARCH_ENTITY_ROLE_TYPE_MISMATCH`    | Papel de empresa (`FUNILARIA`, `MECANICA`, `LOCADORA`) numa pessoa física                   |
| `409` | `IDEMPOTENCY_KEY_REUSED`                | A mesma `Idempotency-Key` já abriu um caso com outro corpo                                  |
| `409` | `RESEARCH_DOCUMENTS_IN_PROGRESS`        | O caso ainda está lendo os arquivos do envio                                                |
| `409` | `VEHICLE_IN_OPEN_RESEARCH`              | A placa já está num caso em aberto do workspace. O corpo traz `researchId` e `licensePlate` |
| `502` | `RESEARCH_ENTITY_PROFILE_LOOKUP_FAILED` | A consulta do cadastro falhou; nada foi gravado                                             |

Dois erros carregam o dado de que você precisa para continuar, em vez de escondê-lo na frase: `VEHICLE_IN_OPEN_RESEARCH` traz o `researchId` do caso aberto — é para onde as evidências devem ir —, e um arquivo recusado no envio traz o `index` dele em `files`, para você corrigir o arquivo certo.

Os demais status seguem o óbvio: `400` entrada malformada, `401` sem token (ou sem usuário), `403` workspace errado, `404` não existe, `413` envio grande demais, `503` a API subiu sem o agente de IA.

## Permissões

Toda rota `/api/v1/lens/...` exige um token Bearer válido, e **o workspace do token tem de ser o do caminho**. Um caso de outro workspace é `403`, nunca `404`: o Lens não conta quem existe fora do seu workspace.

Quem **escreve** precisa, além do token, de um usuário autenticado: o autor do caso vem sempre da identidade do token, nunca do `userId` do corpo, que é ignorado. Escrita sem autor é `401` antes de qualquer gravação — uma escrita sem autor não teria como ser auditada.

Veja [Autenticação](/api/lens/authentication).
