---
url: https://developers.zarv.com/api/lens/quadro.md
description: >-
  O quadro do Lens: as nove raias padrão nas fases COLETA, ANALISE e DESFECHO,
  quem move o caso em cada acontecimento e como montar as colunas pela API.
---

# O quadro

Todo caso do Lens ocupa uma **raia** do quadro kanban do workspace, e o campo `kanbanId` do caso diz qual. O quadro tem três fases, na ordem do trabalho: `COLETA`, `ANALISE` e `DESFECHO`.

O Lens move o caso sozinho a cada acontecimento; o cliente move no que é decisão humana.

## O quadro nasce pronto

Um workspace que nunca leu o quadro recebe as **nove raias padrão** na primeira chamada de `GET .../kanban`, gravadas ali mesmo, com o autor `system`:

| Fase       | Ordem | Raia                     | Quando o caso está nela                |
| ---------- | ----- | ------------------------ | -------------------------------------- |
| `COLETA`   | 1     | **Abertura**             | O caso acabou de nascer                |
| `COLETA`   | 2     | **Dados pendentes**      | Falta material (movimento do analista) |
| `COLETA`   | 3     | **Dados inconsistentes** | O envio dos documentos falhou          |
| `COLETA`   | 4     | **Pronto para análise**  | O envio terminou bem                   |
| `ANALISE`  | 1     | **Analisando**           | A análise está na fila ou rodando      |
| `ANALISE`  | 2     | **Análise falhou**       | A análise terminou em `FAILED`         |
| `ANALISE`  | 3     | **Analisado**            | A análise terminou em `DONE`           |
| `DESFECHO` | 1     | **Reprovado**            | O analista reprovou o caso             |
| `DESFECHO` | 2     | **Aprovado**             | O analista aprovou o caso              |

Os ids das nove são **estáveis**: derivam do workspace, da fase e do nome da raia, então são os mesmos em toda leitura, para sempre. Duas chamadas simultâneas no mesmo workspace gravam cada raia uma única vez.

```sh
curl "https://services.zarv.com/api/v1/lens/$WORKSPACE_ID/kanban" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

```json
[
  {
    "id": "0f3b5d21-9c47-5e8a-b6d2-1a4c7e9f03b8",
    "workspaceId": "3f1a2b4c-5d6e-4f70-8a91-b2c3d4e5f607",
    "userId": "system",
    "phase": "COLETA",
    "step": "Abertura",
    "description": "",
    "order": 1,
    "status": "ACTIVE",
    "createdAt": "2026-11-04T11:59:00Z",
    "updatedAt": "2026-11-04T11:59:00Z"
  }
]
```

A lista vem **na ordem do quadro**: primeiro a fase, depois o `order` dentro da fase e, no empate, a criação. Não há paginação — o quadro tem poucas raias.

Raias `INACTIVE` continuam na lista: esconder uma raia é decisão do cliente, e um caso parado numa raia inativa não some do banco.

## Quem move o caso

### O Lens, nos acontecimentos

| Acontecimento                      | Raia de destino          |
| ---------------------------------- | ------------------------ |
| O caso é aberto                    | **Abertura**             |
| O envio dos documentos termina bem | **Pronto para análise**  |
| O envio falha                      | **Dados inconsistentes** |
| A análise entra na fila            | **Analisando**           |
| A análise termina em `DONE`        | **Analisado**            |
| A análise termina em `FAILED`      | **Análise falhou**       |

Esses movimentos são automáticos e acontecem onde quer que o caso esteja: um caso que o analista havia levado para "Dados pendentes" e que recebe um envio novo volta a andar pela fase de Coleta.

### O cliente, pelo `PUT` do caso

```sh
curl -X PUT "https://services.zarv.com/api/v1/lens/$WORKSPACE_ID/research/$RESEARCH_ID" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "kanbanId": "9d4a1c83-7e26-5f40-ab58-2c6d9e0f4a71" }'
```

Regras do movimento:

* a raia tem de ser uma linha **`ACTIVE`** do quadro **deste** workspace; qualquer outra coisa é `400`;
* com o envio dos documentos ou a análise **em andamento**, o movimento é `409` — naquele momento, o caso é do worker;
* o Lens não restringe o destino. Na prática, o movimento humano é para **Dados pendentes**, **Aprovado** ou **Reprovado**.

## Montar as colunas

Para cada raia, peça a página dela na listagem de casos:

```sh
curl "https://services.zarv.com/api/v1/lens/$WORKSPACE_ID/research?kanbanId=$LANE_ID&limit=20" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

O `total` da resposta passa a ser o **total daquela raia** — é o número que vai no cabeçalho da coluna —, e `data` é a página. Os filtros se combinam: `?kanbanId=…&status=CREATED&search=TST1A23` é a coluna filtrada.

Cada item da lista traz `vehicleCount`, `entityCount` e `documentCount`, que saem da mesma fonte do detalhe: o card e a tela do caso nunca mostram números diferentes.

```js
async function loadBoard(workspaceId, accessToken) {
  const headers = { Authorization: `Bearer ${accessToken}` };
  const base = `https://services.zarv.com/api/v1/lens/${workspaceId}`;

  const lanes = await fetch(`${base}/kanban`, { headers }).then((r) =>
    r.json(),
  );

  return Promise.all(
    lanes
      .filter((lane) => lane.status === "ACTIVE")
      .map(async (lane) => {
        const page = await fetch(
          `${base}/research?kanbanId=${lane.id}&limit=20`,
          { headers },
        ).then((r) => r.json());
        return { lane, cases: page.data, total: page.total };
      }),
  );
}
```

::: tip A Abertura leva os casos antigos
Um caso aberto antes de o Lens guardar a raia não tem `kanbanId`. Ele aparece na **Abertura**: tanto a leitura do caso quanto o filtro `?kanbanId=<Abertura>` o trazem para lá. Nenhum caso fica fora do quadro.
:::

## O quadro é leitura

As rotas públicas do quadro são as duas leituras: a lista e a raia por id. Criar, editar ou apagar raia não é exposto — o quadro das nove raias é o mesmo em todos os workspaces, e é o que o Lens conhece para mover o caso sozinho.

## A raia não decide nada

A raia **reflete** o que já aconteceu. Nenhuma regra do Lens a lê para decidir se um caso pode ser analisado, editado ou enviado: essa decisão é sempre de um campo próprio — `documents.status`, `analysis.status`, o status do caso.

Isso é de propósito. Se a raia decidisse, mover um card na tela mudaria o que o sistema permite — e um analista que arrasta um caso para "Aprovado" estaria, sem saber, liberando ou travando um fluxo. Aqui, ele está registrando uma decisão que já tomou.
