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

# Catálogo de eventos

> Os tipos que o Pictor emite, o que cada um carrega e quais já estão no ar.

Esta é a lista completa dos eventos que o Pictor envia para o seu endereço. Cada
tipo tem nome estável em `recurso.acao` — **o nome não muda**. Quando o conteúdo
de um evento mudar de forma incompatível, ele vira um tipo novo ou ganha uma
`version` nova; o que já existe continua chegando igual.

<Info>
  A mesma lista está em `GET /api/webhooks/event-types`, com os campos de cada
  tipo. Se você gera código a partir do contrato, leia de lá — a página e a rota
  saem da mesma fonte.
</Info>

## Como ler a coluna de estado

| Estado                            | O que significa                                                                                                                                                                                           |
| --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Emitido hoje**                  | Já existe quem produza este fato. Assine e você recebe.                                                                                                                                                   |
| **Reservado — ainda sem emissor** | O nome está reservado e o formato está fechado, mas ninguém produz o fato ainda. Você pode assinar agora: no dia em que o emissor nascer, o seu receptor já está pronto e nada precisa mudar do seu lado. |

<Warning>
  **A entrega é pelo menos uma vez.** O mesmo evento pode chegar mais de uma vez —
  numa reentrega depois de um erro, ou quando a sua resposta demora e nós tentamos
  de novo. Use o cabeçalho `Pictor-Event-Id` para descartar o repetido: ele é o
  mesmo em todas as tentativas do mesmo evento.
</Warning>

## Ronda

### `patrol.completed`

Uma varredura de ronda terminou e a folha está completa.

**Emitido hoje** · versão do conteúdo: `1`

<Note>
  Dispara no fim da VARREDURA, não no fim da corrida da agenda: a corrida encerra por relógio e pode fechar com verificação ainda pendente. O evento aponta a varredura; a folha inteira sai da API de relatórios de ronda, com a sua chave.
</Note>

| Campo de `data` | Tipo     | O que é                                       |
| --------------- | -------- | --------------------------------------------- |
| `alarm_id`      | `uuid`   | O alarme que agrupa a varredura.              |
| `completed_at`  | `string` | Quando a varredura fechou, ISO-8601 com fuso. |

### `patrol.digest_ready`

O resumo do dia agrupando as varreduras foi montado.

**Reservado — ainda sem emissor** · versão do conteúdo: `1`

| Campo de `data` | Tipo      | O que é                            |
| --------------- | --------- | ---------------------------------- |
| `local_date`    | `string`  | O dia local resumido (AAAA-MM-DD). |
| `patrols_total` | `integer` | Varreduras no dia.                 |

## IA e verificação

### `verification.completed`

A verificação por IA terminou, com veredito qualquer.

**Emitido hoje** · versão do conteúdo: `1`

<Note>
  Sai SEMPRE que a verificação termina, inclusive quando ela não viu nada (`label` = `none`). É este o tipo que responde "a ronda rodou".
</Note>

| Campo de `data` | Tipo             | O que é                                       |
| --------------- | ---------------- | --------------------------------------------- |
| `device_id`     | `uuid`           | Câmera que produziu o quadro.                 |
| `external_id`   | `string \| null` | Identificador da câmera no seu cadastro.      |
| `label`         | `string \| null` | O veredito: person, vehicle, none, uncertain. |
| `score`         | `number \| null` | Confiança de 0 a 1.                           |
| `detected_at`   | `string`         | Quando aconteceu, ISO-8601 com fuso.          |

### `verification.person_detected`

Uma pessoa foi detectada na cena.

**Emitido hoje** · versão do conteúdo: `1`

<Note>
  O evento não carrega imagem. Busque o quadro pela API com a sua chave.
</Note>

| Campo de `data` | Tipo             | O que é                                  |
| --------------- | ---------------- | ---------------------------------------- |
| `device_id`     | `uuid`           | Câmera que produziu o quadro.            |
| `external_id`   | `string \| null` | Identificador da câmera no seu cadastro. |
| `score`         | `number \| null` | Confiança de 0 a 1.                      |
| `detected_at`   | `string`         | Quando aconteceu, ISO-8601 com fuso.     |

### `verification.vehicle_detected`

Um veículo foi detectado na cena.

**Emitido hoje** · versão do conteúdo: `1`

<Note>
  O evento não carrega imagem nem placa.
</Note>

| Campo de `data` | Tipo             | O que é                                  |
| --------------- | ---------------- | ---------------------------------------- |
| `device_id`     | `uuid`           | Câmera que produziu o quadro.            |
| `external_id`   | `string \| null` | Identificador da câmera no seu cadastro. |
| `label`         | `string \| null` | car, truck, motorcycle, …                |
| `score`         | `number \| null` | Confiança de 0 a 1.                      |
| `detected_at`   | `string`         | Quando aconteceu, ISO-8601 com fuso.     |

### `verification.obstruction_suspected`

A cena parece obstruída (lente tapada, mira mexida).

**Reservado — ainda sem emissor** · versão do conteúdo: `1`

| Campo de `data` | Tipo     | O que é                              |
| --------------- | -------- | ------------------------------------ |
| `device_id`     | `uuid`   | Câmera avaliada.                     |
| `detected_at`   | `string` | Quando aconteceu, ISO-8601 com fuso. |

## Equipamento

### `device.offline`

A câmera parou de responder.

**Emitido hoje** · versão do conteúdo: `1`

<Note>
  A sonda é TCP na porta de vídeo e cobre câmera com endereço próprio. Câmera de nuvem P2P não tem endereço fixo e fica de fora — ausente é honesto, 'offline' seria mentira.
</Note>

| Campo de `data`   | Tipo             | O que é                                    |
| ----------------- | ---------------- | ------------------------------------------ |
| `device_id`       | `uuid`           | A câmera.                                  |
| `external_id`     | `string \| null` | Identificador dela no seu cadastro.        |
| `previous_status` | `string`         | O estado de onde ela saiu.                 |
| `changed_at`      | `string`         | Quando a transição foi aplicada, ISO-8601. |

### `device.online`

A câmera voltou a responder.

**Emitido hoje** · versão do conteúdo: `1`

| Campo de `data`   | Tipo             | O que é                                    |
| ----------------- | ---------------- | ------------------------------------------ |
| `device_id`       | `uuid`           | A câmera.                                  |
| `external_id`     | `string \| null` | Identificador dela no seu cadastro.        |
| `previous_status` | `string`         | O estado de onde ela saiu.                 |
| `changed_at`      | `string`         | Quando a transição foi aplicada, ISO-8601. |

### `device.no_frame`

A câmera responde no endereço, mas não entrega quadro.

**Reservado — ainda sem emissor** · versão do conteúdo: `1`

<Note>
  Este é o evento que fecha o laço de manutenção: recebido, o seu sistema abre a ordem de serviço sozinho.
</Note>

| Campo de `data` | Tipo             | O que é                             |
| --------------- | ---------------- | ----------------------------------- |
| `device_id`     | `uuid`           | A câmera.                           |
| `external_id`   | `string \| null` | Identificador dela no seu cadastro. |
| `last_frame_at` | `string \| null` | Último quadro observado, ISO-8601.  |

### `device.recorder_offline`

O gravador (appliance ou DVR) parou de reportar.

**Reservado — ainda sem emissor** · versão do conteúdo: `1`

| Campo de `data` | Tipo             | O que é                            |
| --------------- | ---------------- | ---------------------------------- |
| `appliance_id`  | `uuid`           | O gravador.                        |
| `observed_at`   | `string \| null` | Último reporte recebido, ISO-8601. |

### `device.recorder_online`

O gravador voltou a reportar.

**Reservado — ainda sem emissor** · versão do conteúdo: `1`

| Campo de `data` | Tipo             | O que é                             |
| --------------- | ---------------- | ----------------------------------- |
| `appliance_id`  | `uuid`           | O gravador.                         |
| `observed_at`   | `string \| null` | Reporte que restabeleceu, ISO-8601. |

### `device.retention_below_contract`

A retenção de gravação caiu abaixo do contratado.

**Reservado — ainda sem emissor** · versão do conteúdo: `1`

| Campo de `data`   | Tipo      | O que é                       |
| ----------------- | --------- | ----------------------------- |
| `device_id`       | `uuid`    | A câmera ou o gravador.       |
| `days_observed`   | `integer` | Dias de gravação encontrados. |
| `days_contracted` | `integer` | Dias que o contrato prevê.    |

## Alarme

### `alarm.received`

Um alarme entrou pelo canal de eventos.

**Emitido hoje** · versão do conteúdo: `1`

<Note>
  Sai só na PRIMEIRA vez. Retransmissão do mesmo disparo é dedupada antes de virar evento — se ela também emitisse, o seu sistema abriria duas ocorrências para o mesmo alarme.
</Note>

| Campo de `data` | Tipo     | O que é                                   |
| --------------- | -------- | ----------------------------------------- |
| `alarm_id`      | `uuid`   | O alarme. É o mesmo id que a API devolve. |
| `provider`      | `string` | Por qual canal ele entrou.                |
| `received_at`   | `string` | Quando chegou, ISO-8601 com fuso.         |

### `alarm.verified`

A IA CONFIRMOU o alarme — viu alguma coisa na cena.

**Emitido hoje** · versão do conteúdo: `1`

<Note>
  Só quando a IA confirma. A verificação que terminou sem ver nada sai como verification.completed e NÃO como este tipo — assine os dois se precisa saber que a varredura rodou.
</Note>

| Campo de `data` | Tipo             | O que é                                  |
| --------------- | ---------------- | ---------------------------------------- |
| `alarm_id`      | `uuid \| null`   | O alarme verificado.                     |
| `device_id`     | `uuid`           | Câmera que produziu o quadro.            |
| `external_id`   | `string \| null` | Identificador da câmera no seu cadastro. |
| `label`         | `string`         | O veredito: person, vehicle, uncertain.  |
| `score`         | `number \| null` | Confiança de 0 a 1.                      |
| `verified_at`   | `string`         | Quando o veredito saiu, ISO-8601.        |

## Entrega de relatório

### `report.delivered`

O relatório saiu para a lista de destinatários.

**Emitido hoje** · versão do conteúdo: `1`

<Note>
  'Entregue' aqui é 'o transporte aceitou'. Não é prova de que a pessoa recebeu — para isso existe report.opened.
</Note>

| Campo de `data` | Tipo     | O que é                                |
| --------------- | -------- | -------------------------------------- |
| `local_date`    | `string` | O dia local resumido (AAAA-MM-DD).     |
| `delivered_at`  | `string` | Quando o transporte aceitou, ISO-8601. |

### `report.opened`

Alguém abriu o relatório pelo link assinado.

**Emitido hoje** · versão do conteúdo: `1`

<Note>
  Sai UMA vez por relatório, na primeira abertura — recarregar a página não gera outro. É prova PARCIAL de entrega: a ausência do evento não prova que não chegou, porque quem lê o e-mail e não clica no link não gera evento nenhum. Não monte SLA de entrega em cima da ausência dele.
</Note>

| Campo de `data` | Tipo     | O que é                               |
| --------------- | -------- | ------------------------------------- |
| `alarm_id`      | `uuid`   | A varredura aberta.                   |
| `opened_at`     | `string` | Quando foi aberto, ISO-8601 com fuso. |

## Serviço

### `webhook.test`

Evento de teste, disparado por você no console.

**Emitido hoje** · versão do conteúdo: `1`

<Note>
  Vai só para o endpoint em que você pediu, e nunca para os outros. É o único tipo que não descreve um fato do vídeo.
</Note>

| Campo de `data` | Tipo     | O que é                            |
| --------------- | -------- | ---------------------------------- |
| `message`       | `string` | Texto fixo que identifica o teste. |
| `requested_by`  | `string` | Quem pediu o disparo.              |

## O que nenhum evento carrega

Nenhum tipo desta lista traz imagem, rosto, placa, nome, e-mail ou telefone. O
evento **aponta** para o recurso (`device_id`, `alarm_id`, um link assinado com
prazo) e você busca o conteúdo pela API, com a sua chave — assim o acesso fica
registrado do seu lado e do nosso, e o corpo do webhook não vira um depósito de
dado pessoal no seu servidor de recepção.

## A janela de repetição

Cada entrega leva um carimbo de tempo assinado. Recuse o que chegar com mais de **300 segundos** de diferença do seu relógio: é assim que uma entrega capturada hoje deixa de valer amanhã.
