---
updatedAt: 2026-04-23T14:41:21.000Z
agentTools:
  projectIndex: https://docs.cobli.co/llms.txt
---

# Geração da página de acompanhamento do veículo

Gera o acompanhamento em tempo real do veículo.
A página gerada expira após um período de tempo:
  - Se o veículo não chegou ao local de destino dentro de 24 horas a partir do momento em que a página foi gerada
  (a partir do momento em que a requisição para a API foi feita com sucesso).

  - Em uma hora após o momento em que o veículo chegou ao local de destino.

Com esse endpoint você pode:

  - Saber a localização precisa em tempo real da sua frota

# OpenAPI definition

````json
{
  "openapi": "3.1.0",
  "info": {
    "version": "1.0",
    "title": "Cobli REST API",
    "contact": {
      "name": "Cobli",
      "url": "https://cobli.co/contato/",
      "email": "suporte@cobli.co"
    },
    "termsOfService": "https://cobli.co/terms/",
    "x-logo": {
      "url": "/favicon.png"
    },
    "description": "# Introdução\nTodos os endpoints que não lidam com upload de arquivos, recebem e retornam\ndocumentos JSON no corpo da requisição HTTP. Os endpoints que precisam de\nautenticação ou identificação esperamos que os parâmetros sejam enviados no\ncabeçalho da requisição (HTTP Header).\n\nO único protocolo de comunicação aceito é o HTTPS. Toda requisição feita em\nHTTP será redirecionada para HTTPS. A API sempre terá um certificado válido,\nentão não é necessário desabilitar ou alterar qualquer configuração no que\nse refere a certificados.\n\n# Máximo de Requisições\nTodas as requisições para a API, oriundas do mesmo IP, tem uma limitação de\n50 requests por segundo. Qualquer requisição além desse limite será\ndescartada e receberá como resposta `TooManyRequests` (Status 429).\n\n# Autenticação\n<SecurityDefinitions />\n\n# Webhooks\n\nA Cobli envia um `POST` HTTP para sua URL toda vez que algo relevante acontece\nna frota — sem polling. Use webhooks para alertas em tempo real, integração\ncom ERP/BI, automação de fluxos a partir de eventos de ignição, geocerca,\nvelocidade, bateria e câmera.\n\n### 1. Configurar em 3 passos\n\n1. **Crie um endpoint HTTPS** na sua aplicação que aceite `POST application/json`\n   e responda `2xx` em até **5 segundos** (processe de forma assíncrona se necessário).\n2. **Cadastre a assinatura** no painel Cobli em [Integrações → Webhooks](https://painel.cobli.co/webhooks):\n   URL, secret key, tipos de evento, e opcionalmente custom headers.\n3. **Teste** — gere um evento no veículo ou use o botão \"Disparar evento de teste\"\n   no painel.\n\n### 2. Eventos disponíveis (28 tipos em produção)\n\n| Categoria | Tipo de assinatura | `eventType` entregue |\n|-----------|--------------------|----------------------|\n| Ponto de interesse | `geofence_in`, `geofence_out` | `geofence_in`, `geofence_out` |\n| Ignição | `ignition_on`, `ignition_off` | `ignition_on`, `ignition_off` |\n| Posição | `position`, `position_sleep` | `position`, `position_sleep` (janela de 3 min — sua aplicação não recebe cada ping GPS) |\n| Velocidade | `speed` | `alert_driven_over_speed`, `end_alert_driven_over_speed` |\n| Bateria | `battery_external_low`, `battery_external_disconnected`, `battery_external_reconnected` | idem |\n| Câmera (frotas com câmera Cobli) | um por tipo | `hard_break`, `fast_acceleration`, `speedy_turn`, `tailgating`, `front_collision_warning`, `distracted_driving`, `eyes_closed`, `phone_usage`, `smoking`, `yawn`, `sos` |\n| Rotas e paradas | `routes`, `activities` | `route_started`, `route_finished`, `activity_completed`, `activity_failed` |\n| Configuração do veículo (hardware compatível) | `ignition_lock_status_changed`, `allow_list_changed` | idem |\n\n**Cada tipo está documentado individualmente** — com envelope, `eventData`,\nexemplo e o efeito de cada resposta do seu endpoint — na seção\n**Eventos de Webhook** do menu lateral.\n\n> **`speed`** entrega os dois eventos de velocidade: são inseparáveis.\n> **`routes`** e **`activities`** são grupos de **composição fechada** — assinar o\n> grupo entrega exatamente os tipos listados acima e nada mais, e um tipo novo do\n> catálogo **não** passa a ser entregue sem que você atualize a assinatura. Os dois\n> nomes são **plurais**: grave `\"routes\"` e `\"activities\"` literalmente em\n> `event_types`.\n\n### 3. Envelope do evento\n\nTodo evento segue o mesmo envelope JSON (camelCase no formato padrão):\n\n```json\n{\n  \"eventId\":   \"7decdf99-283d-4c70-9b95-a3b3f896e9b9\",\n  \"eventTime\": \"2024-03-15T10:23:07Z\",\n  \"eventType\": \"geofence_in\",\n  \"eventData\": {\n    \"deviceId\":     \"879797465464874\",\n    \"vehicleId\":    \"05009b4a-bed3-4431-955a-4c3e80dc6697\",\n    \"fleetId\":      \"cf3f1990-2ce3-4ed9-85c5-9a528295ecfe\",\n    \"licensePlate\": \"ABC1D23\",\n    \"latitude\":     -23.764235,\n    \"longitude\":    -46.595110,\n    \"geofenceId\":   \"59e88bca-d3b9-4980-95a9-421fe2ffb275\",\n    \"name\":         \"MEU LOCAL DE INTERESSE\"\n  }\n}\n```\n\n- **`eventId`** é determinístico — o mesmo evento sempre traz o mesmo `eventId`\n  em retentativas e recuperações. **Use para deduplicar** no seu lado\n  (`Redis SETNX`, Postgres unique).\n- **`eventTime`** é o timestamp ISO 8601 UTC do evento no veículo.\n- **`eventData`** varia por tipo. Campos como `rpm`, `fuelLevel`, `cobliId` podem\n  ausentar dependendo do dispositivo — projete tolerância a campos opcionais ausentes.\n\n### 4. Autenticação (HMAC-SHA256)\n\nToda requisição traz o header `X-Cobli-Signature` — HMAC-SHA256 do body em hex.\n**Sempre valide** antes de processar; rejeite com `400` se inválido.\n\n```js\nimport crypto from \"crypto\";\n\nconst expected = crypto.createHmac(\"sha256\", SECRET).update(body).digest(\"hex\");\nconst valid = crypto.timingSafeEqual(\n  Buffer.from(expected, \"hex\"),\n  Buffer.from(req.header(\"X-Cobli-Signature\"), \"hex\"),\n);\nif (!valid) return res.status(400).send(\"invalid signature\");\n```\n\n> Compare com `timingSafeEqual` ou equivalente — comparação string normal vaza\n> tempo. O corpo HMACado é o **byte UTF-8 cru** que sua aplicação recebeu;\n> não normalize, não re-encode JSON.\n\n**Bearer auth (OAuth dinâmico)** é opcional para endpoints que exigem token rotativo.\nPara habilitar, abra ticket via `#help-tech-account-mgm` informando `token_url` e credenciais.\n\n### 5. Custom headers\n\nCada assinatura aceita um mapa de headers HTTP adicionais (`X-Tenant`, `X-App-Version`,\nAPI keys estáticas, etc.) injetados em toda entrega. `X-Cobli-Signature`,\n`Authorization`, `Content-Type` e `User-Agent` são reservados e não podem ser\nsobrescritos.\n\n### 6. Entrega confiável\n\n| Resposta do seu endpoint | Comportamento |\n|--------------------------|--------------|\n| `2xx` | Entrega confirmada |\n| `4xx` (exceto `429` e `401` com Bearer auth) | Falha permanente — não retentado |\n| `401` com Bearer auth habilitado | Renova o token e retenta |\n| `429` | Retentado com `Retry-After` (truncado em 15 s) ou backoff exponencial |\n| `5xx` ou timeout (>5 s) | Retentado: até **5 tentativas**, com intervalos de **2 s → 4 s → 8 s → 15 s** |\n| Erro de rede (`-1` na recuperação) | Retentado idem |\n| Circuit aberto (`-3` na recuperação) | 5+ falhas consecutivas → pausa 60 s para essa URL |\n\nApós **7 dias de falha contínua**, a assinatura é **desativada automaticamente**\n(`active = false`) — reabilite no painel após corrigir.\n\n> A Cobli mantém **no máximo 1 request em voo por hostname**. Para paralelismo,\n> divida em múltiplos hostnames.\n\n### 7. Recuperar eventos perdidos (até 15 dias)\n\nUse `GET /public/v2/events` para reconciliar entregas dos últimos 15 dias —\nútil quando seu sistema ficou fora do ar, ou para auditoria.\nVeja o endpoint na seção dedicada abaixo.\n\nO `payload` retornado é **semanticamente equivalente** ao que sua aplicação recebeu\nvia push — mesmos campos e valores, com o mesmo `eventId` —, permitindo deduplicar\ndiretamente contra eventos já processados. Como ele é reserializado como JSON nativo,\nnão serve para revalidar o `X-Cobli-Signature` da entrega original.\n\n### 8. Idempotência\n\nSempre dedupe por `eventId`. Padrão típico:\n\n```sql\nINSERT INTO webhook_processed (event_id, ...) VALUES ($1, ...)\nON CONFLICT (event_id) DO NOTHING;\n```\n\nA Cobli não garante ordem entre devices diferentes. Dentro de um device, a ordem\né best-effort; use `eventTime` para ordenar quando crítico.\n\n### 9. Troubleshooting rápido\n\n- **Não recebo evento X** → assinatura ativa? `eventType` na lista? endpoint responde\n  `2xx`? HMAC válido?\n- **Recebo duplicado** → esperado em retentativas/recuperação; dedupe por `eventId`.\n- **`eventData` aninhado** → esperado em `route_started`, `route_finished`,\n  `activity_completed` e `activity_failed`: os campos vivem em `eventData.route` e\n  `eventData.activity`. Nesses quatro tipos `deviceId`, `vehicleId` e `licensePlate`\n  também podem ser omitidos.\n- **Campos de telemetria como `null`** → esperado em `ignition_lock_status_changed` e\n  `allow_list_changed`: esses eventos descrevem estado de configuração, não telemetria.\n- **Payload em `snake_case`** → sua assinatura está no formato legado, aplicado apenas a\n  `geofence_in` e `geofence_out`. O formato não muda; para migrar para o canônico\n  (`camelCase`), abra ticket.\n- **Assinatura desativada** → 7 dias de falha persistente. Use `GET /public/v2/events?statusCode=...`\n  para investigar e corrigir antes de reabilitar.\n\n### 10. Onde pedir ajuda\n\nSlack `#help-tech-account-mgm` com `fleetId`, `eventType` e janela de tempo\n(`startDate`/`endDate`). Bugs de entrega, habilitar Bearer auth e migrar do formato\nlegado: mesmo canal.\n"
  },
  "servers": [
    {
      "url": "https://api.cobli.co"
    }
  ],
  "tags": [
    {
      "name": "Monitoramento",
      "x-readme": {
        "id": "monitoramento"
      },
      "description": "As rotas de monitoramento auxiliam na gestão em tempo real da sua frota, obtendo dados de eventos relevantes no momento em que eles ocorrem.\nNesses endpoints você pode:\n\n  - gerar um relatório de incidentes.\n\n  - saber quando seus veículos chegarão ao seus destinos.\n\n  - criar uma página de acompanhamento em tempo real de um veículo.\n\n  - obter uma lista de todos os seus dispositivos, com um maior volume de dados, podendo filtrar os dispositivos ativos ou inativos.\n\n  - obter uma lista paginada dos seus dispositivos, com dados prontos para consumo.\n\n  - capturar as últimas localizações dos dispositivos.\n\n  - acompanhar a rota de um dispositivo."
    },
    {
      "name": "Eventos de Webhook",
      "x-readme": {
        "id": "eventos-de-webhook"
      },
      "description": "Catálogo completo dos eventos que a Cobli envia por `POST` para a URL da sua assinatura. Cada entrada descreve o envelope, o `eventData` do tipo, um exemplo real e o que a Cobli faz com cada resposta do seu endpoint.\n\nOs schemas descrevem o **formato canônico** (`camelCase`). Assinaturas criadas antes da migração recebem `geofence_in` e `geofence_out` em `snake_case` — os dois únicos tipos afetados; veja a ressalva na página de cada um.\n\nNesses eventos você pode:\n\n\n  - reagir em tempo real a ponto de interesse, ignição, posição, velocidade, bateria e câmera.\n\n\n  - acompanhar o ciclo de vida de rotas e paradas de Serviços e Entregas.\n\n\n  - observar mudanças de configuração do veículo, como trava de ignição e lista de motoristas autorizados."
    }
  ],
  "paths": {
    "/herbie-1.1/dash/vehicle/eta": {
      "post": {
        "description": "Gera o acompanhamento em tempo real do veículo.\nA página gerada expira após um período de tempo:\n  - Se o veículo não chegou ao local de destino dentro de 24 horas a partir do momento em que a página foi gerada\n  (a partir do momento em que a requisição para a API foi feita com sucesso).\n\n  - Em uma hora após o momento em que o veículo chegou ao local de destino.\n\nCom esse endpoint você pode:\n\n  - Saber a localização precisa em tempo real da sua frota",
        "security": [
          {
            "APIKey": []
          }
        ],
        "tags": [
          "Monitoramento"
        ],
        "operationId": "eta",
        "summary": "Geração da página de acompanhamento do veículo",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "device_id": {
                    "description": "UUID do dispositivo",
                    "type": "string"
                  },
                  "destination": {
                    "type": "object",
                    "description": "Detalhes do destino do veículo",
                    "properties": {
                      "address": {
                        "type": "string",
                        "description": "Endereço de destino por extenso. Este valor aparecerá no campo Destino da página gerada"
                      },
                      "lat": {
                        "type": "number",
                        "description": "Latitude do destino"
                      },
                      "lng": {
                        "type": "number",
                        "description": "Longitude do destino"
                      }
                    }
                  }
                },
                "required": [
                  "device_id",
                  "destination"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "URL para a página de acompanhamento do veículo",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "url": {
                      "type": "string",
                      "description": "URL com o acompanhamento do veículo, exemplo: https://estouchegando.cobli.co/?3N3ABC"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Parâmetros errados",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "message": "Bad request"
                }
              }
            }
          },
          "401": {
            "description": "Chave API inválida ou ausente",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "message": "Unauthorized"
                }
              }
            }
          },
          "500": {
            "description": "Erro no servidor",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "message": "Internal Server error"
                }
              }
            }
          }
        }
      }
    }
  },
  "webhooks": {
    "geofence_in": {
      "post": {
        "tags": [
          "Eventos de Webhook"
        ],
        "operationId": "webhookGeofenceIn",
        "summary": "geofence_in — Veículo entrou em um ponto de interesse",
        "description": "Disparado na **entrada** de um ponto de interesse cadastrado na frota.\n\nO ponto cruzado vem em `geofenceId`, `name` e `address`. Veículos sem posição\nválida no instante do cruzamento não geram o evento.\n\n> **Formato legado.** Assinaturas criadas antes da migração recebem `geofence_in`\n> e `geofence_out` em **`snake_case`** — `event_id`, `event_type`, `event_time`,\n> `event_data` —, com `event_time` em `\"yyyy-MM-dd HH:mm:ss\"` (UTC) e sem\n> `vehicleId`. Se é o seu caso, o schema abaixo não descreve o corpo que você\n> recebe. Esses são os dois únicos tipos afetados; para migrar para o formato\n> canônico, abra ticket em `#help-tech-account-mgm`.\n\n---\n\nAssine o tipo **`geofence_in`** para receber este evento.\nA Cobli envia este evento como `POST application/json` para a URL cadastrada na\nassinatura, assinado em `X-Cobli-Signature`. Responda `2xx` em até 5 segundos e\ndeduplique por `eventId`.\n",
        "security": [
          {
            "CobliWebhookSignature": []
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Envelope do evento `geofence_in`.",
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/EventEnvelope"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "eventType": {
                        "type": "string",
                        "enum": [
                          "geofence_in"
                        ]
                      },
                      "eventData": {
                        "$ref": "#/components/schemas/GeofenceEventData"
                      }
                    }
                  }
                ]
              },
              "example": {
                "eventId": "7decdf99-283d-4c70-9b95-a3b3f896e9b9",
                "eventTime": "2024-03-15T10:23:07Z",
                "eventType": "geofence_in",
                "eventData": {
                  "deviceId": "879797465464874",
                  "vehicleId": "05009b4a-bed3-4431-955a-4c3e80dc6697",
                  "fleetId": "cf3f1990-2ce3-4ed9-85c5-9a528295ecfe",
                  "licensePlate": "ABC1D23",
                  "cobliId": "R875",
                  "driverId": "d1234567-0000-0000-0000-000000000001",
                  "latitude": -23.764235,
                  "longitude": -46.59511,
                  "geofenceId": "59e88bca-d3b9-4980-95a9-421fe2ffb275",
                  "name": "MEU LOCAL DE INTERESSE",
                  "address": "Rua Lourenço Marques, 297, São Paulo - SP, 04547-100",
                  "speedInKmh": 12.5,
                  "odometer": 45230.5
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/WebhookAck"
          },
          "400": {
            "$ref": "#/components/responses/WebhookRejected"
          },
          "429": {
            "$ref": "#/components/responses/WebhookThrottled"
          },
          "500": {
            "$ref": "#/components/responses/WebhookServerError"
          }
        }
      }
    },
    "geofence_out": {
      "post": {
        "tags": [
          "Eventos de Webhook"
        ],
        "operationId": "webhookGeofenceOut",
        "summary": "geofence_out — Veículo saiu de um ponto de interesse",
        "description": "Disparado na **saída** de um ponto de interesse cadastrado na frota.\n\nO ponto cruzado vem em `geofenceId`, `name` e `address`. Veículos sem posição\nválida no instante do cruzamento não geram o evento.\n\n> **Formato legado.** Assinaturas criadas antes da migração recebem `geofence_in`\n> e `geofence_out` em **`snake_case`** — `event_id`, `event_type`, `event_time`,\n> `event_data` —, com `event_time` em `\"yyyy-MM-dd HH:mm:ss\"` (UTC) e sem\n> `vehicleId`. Se é o seu caso, o schema abaixo não descreve o corpo que você\n> recebe. Esses são os dois únicos tipos afetados; para migrar para o formato\n> canônico, abra ticket em `#help-tech-account-mgm`.\n\n---\n\nAssine o tipo **`geofence_out`** para receber este evento.\nA Cobli envia este evento como `POST application/json` para a URL cadastrada na\nassinatura, assinado em `X-Cobli-Signature`. Responda `2xx` em até 5 segundos e\ndeduplique por `eventId`.\n",
        "security": [
          {
            "CobliWebhookSignature": []
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Envelope do evento `geofence_out`.",
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/EventEnvelope"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "eventType": {
                        "type": "string",
                        "enum": [
                          "geofence_out"
                        ]
                      },
                      "eventData": {
                        "$ref": "#/components/schemas/GeofenceEventData"
                      }
                    }
                  }
                ]
              },
              "example": {
                "eventId": "7decdf99-283d-4c70-9b95-a3b3f896e9b9",
                "eventTime": "2024-03-15T10:23:07Z",
                "eventType": "geofence_out",
                "eventData": {
                  "deviceId": "879797465464874",
                  "vehicleId": "05009b4a-bed3-4431-955a-4c3e80dc6697",
                  "fleetId": "cf3f1990-2ce3-4ed9-85c5-9a528295ecfe",
                  "licensePlate": "ABC1D23",
                  "cobliId": "R875",
                  "driverId": "d1234567-0000-0000-0000-000000000001",
                  "latitude": -23.764235,
                  "longitude": -46.59511,
                  "geofenceId": "59e88bca-d3b9-4980-95a9-421fe2ffb275",
                  "name": "MEU LOCAL DE INTERESSE",
                  "address": "Rua Lourenço Marques, 297, São Paulo - SP, 04547-100",
                  "speedInKmh": 12.5,
                  "odometer": 45230.5
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/WebhookAck"
          },
          "400": {
            "$ref": "#/components/responses/WebhookRejected"
          },
          "429": {
            "$ref": "#/components/responses/WebhookThrottled"
          },
          "500": {
            "$ref": "#/components/responses/WebhookServerError"
          }
        }
      }
    },
    "ignition_on": {
      "post": {
        "tags": [
          "Eventos de Webhook"
        ],
        "operationId": "webhookIgnitionOn",
        "summary": "ignition_on — Ignição ligada",
        "description": "Disparado na transição do estado da ignição para **ligada**. O campo `ignition`\ndo payload traz o estado resultante (`\"ON\"`).\n\n`driverId` é incluído quando um motorista está identificado no veículo no momento\ndo evento.\n\n---\n\nAssine o tipo **`ignition_on`** para receber este evento.\nA Cobli envia este evento como `POST application/json` para a URL cadastrada na\nassinatura, assinado em `X-Cobli-Signature`. Responda `2xx` em até 5 segundos e\ndeduplique por `eventId`.\n",
        "security": [
          {
            "CobliWebhookSignature": []
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Envelope do evento `ignition_on`.",
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/EventEnvelope"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "eventType": {
                        "type": "string",
                        "enum": [
                          "ignition_on"
                        ]
                      },
                      "eventData": {
                        "$ref": "#/components/schemas/IgnitionEventData"
                      }
                    }
                  }
                ]
              },
              "example": {
                "eventId": "a1b2c3d4-0000-0000-0000-111122223333",
                "eventTime": "2024-03-15T08:00:00Z",
                "eventType": "ignition_on",
                "eventData": {
                  "deviceId": "879797465464874",
                  "vehicleId": "05009b4a-bed3-4431-955a-4c3e80dc6697",
                  "fleetId": "cf3f1990-2ce3-4ed9-85c5-9a528295ecfe",
                  "licensePlate": "ABC1D23",
                  "cobliId": "R875",
                  "driverId": "d1234567-0000-0000-0000-000000000001",
                  "latitude": -23.55052,
                  "longitude": -46.633308,
                  "heading": 90,
                  "speedInKmh": 15.3,
                  "ignition": "ON",
                  "odometer": 45230.5,
                  "batteryVoltage": 12450,
                  "connectionType": "FOUR_G_LTE"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/WebhookAck"
          },
          "400": {
            "$ref": "#/components/responses/WebhookRejected"
          },
          "429": {
            "$ref": "#/components/responses/WebhookThrottled"
          },
          "500": {
            "$ref": "#/components/responses/WebhookServerError"
          }
        }
      }
    },
    "ignition_off": {
      "post": {
        "tags": [
          "Eventos de Webhook"
        ],
        "operationId": "webhookIgnitionOff",
        "summary": "ignition_off — Ignição desligada",
        "description": "Disparado na transição do estado da ignição para **desligada**. O campo `ignition`\ndo payload traz o estado resultante (`\"OFF\"`).\n\n`driverId` é incluído quando um motorista está identificado no veículo no momento\ndo evento.\n\n---\n\nAssine o tipo **`ignition_off`** para receber este evento.\nA Cobli envia este evento como `POST application/json` para a URL cadastrada na\nassinatura, assinado em `X-Cobli-Signature`. Responda `2xx` em até 5 segundos e\ndeduplique por `eventId`.\n",
        "security": [
          {
            "CobliWebhookSignature": []
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Envelope do evento `ignition_off`.",
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/EventEnvelope"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "eventType": {
                        "type": "string",
                        "enum": [
                          "ignition_off"
                        ]
                      },
                      "eventData": {
                        "$ref": "#/components/schemas/IgnitionEventData"
                      }
                    }
                  }
                ]
              },
              "example": {
                "eventId": "a1b2c3d4-0000-0000-0000-111122223333",
                "eventTime": "2024-03-15T08:00:00Z",
                "eventType": "ignition_off",
                "eventData": {
                  "deviceId": "879797465464874",
                  "vehicleId": "05009b4a-bed3-4431-955a-4c3e80dc6697",
                  "fleetId": "cf3f1990-2ce3-4ed9-85c5-9a528295ecfe",
                  "licensePlate": "ABC1D23",
                  "cobliId": "R875",
                  "driverId": "d1234567-0000-0000-0000-000000000001",
                  "latitude": -23.55052,
                  "longitude": -46.633308,
                  "heading": 90,
                  "speedInKmh": 15.3,
                  "ignition": "OFF",
                  "odometer": 45230.5,
                  "batteryVoltage": 12450,
                  "connectionType": "FOUR_G_LTE"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/WebhookAck"
          },
          "400": {
            "$ref": "#/components/responses/WebhookRejected"
          },
          "429": {
            "$ref": "#/components/responses/WebhookThrottled"
          },
          "500": {
            "$ref": "#/components/responses/WebhookServerError"
          }
        }
      }
    },
    "position": {
      "post": {
        "tags": [
          "Eventos de Webhook"
        ],
        "operationId": "webhookPosition",
        "summary": "position — Posição periódica com ignição ligada",
        "description": "Posição periódica do veículo com a ignição **ligada**.\n\n### Janelamento de 3 minutos\n\nA Cobli **não** entrega cada ping GPS. Aplica-se uma janela de **3 minutos** por\ndispositivo:\n\n- O primeiro evento é entregue assim que o dispositivo transmite uma posição válida\n  no estado de ignição atual.\n- Depois de uma entrega, os pings seguintes são **descartados** até completar 3\n  minutos desde o último envio.\n- Passados os 3 minutos, o próximo ping disponível é entregue e o ciclo recomeça.\n- Uma **mudança de estado da ignição** força o envio imediato, sem esperar o ciclo —\n  é o que garante que a transição entre `position` e `position_sleep` apareça no fluxo.\n\nNa prática, 100 veículos em movimento contínuo geram **no máximo ~33 eventos por\nminuto** (100 ÷ 3), não centenas de pings.\n\n> Se a sua aplicação precisa de rastreamento contínuo, ping a ping, o webhook **não\n> é o canal correto** — use `GET /public/v1/paths`. Webhook é otimizado para eventos\n> discretos.\n\n---\n\nAssine o tipo **`position`** para receber este evento.\nA Cobli envia este evento como `POST application/json` para a URL cadastrada na\nassinatura, assinado em `X-Cobli-Signature`. Responda `2xx` em até 5 segundos e\ndeduplique por `eventId`.\n",
        "security": [
          {
            "CobliWebhookSignature": []
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Envelope do evento `position`.",
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/EventEnvelope"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "eventType": {
                        "type": "string",
                        "enum": [
                          "position"
                        ]
                      },
                      "eventData": {
                        "$ref": "#/components/schemas/PositionEventData"
                      }
                    }
                  }
                ]
              },
              "example": {
                "eventId": "b2c3d4e5-0000-0000-0000-222233334444",
                "eventTime": "2024-03-15T10:00:00Z",
                "eventType": "position",
                "eventData": {
                  "deviceId": "879797465464874",
                  "vehicleId": "05009b4a-bed3-4431-955a-4c3e80dc6697",
                  "fleetId": "cf3f1990-2ce3-4ed9-85c5-9a528295ecfe",
                  "licensePlate": "ABC1D23",
                  "cobliId": "R875",
                  "latitude": -23.55052,
                  "longitude": -46.633308,
                  "heading": 180,
                  "ignition": "ON",
                  "odometer": 45245,
                  "numberOfSatellites": 12,
                  "hdop": 0.9,
                  "batteryVoltage": 12480,
                  "connectionType": "FOUR_G_LTE",
                  "speedInKmh": 45.2,
                  "rpm": 1800,
                  "fuelLevel": 68
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/WebhookAck"
          },
          "400": {
            "$ref": "#/components/responses/WebhookRejected"
          },
          "429": {
            "$ref": "#/components/responses/WebhookThrottled"
          },
          "500": {
            "$ref": "#/components/responses/WebhookServerError"
          }
        }
      }
    },
    "position_sleep": {
      "post": {
        "tags": [
          "Eventos de Webhook"
        ],
        "operationId": "webhookPositionSleep",
        "summary": "position_sleep — Posição periódica com ignição desligada",
        "description": "Posição periódica do veículo com a ignição **desligada**.\n\nCom a ignição desligada, `speedInKmh` é omitido e `rpm` vem como `null`.\n\n### Janelamento de 3 minutos\n\nA Cobli **não** entrega cada ping GPS. Aplica-se uma janela de **3 minutos** por\ndispositivo:\n\n- O primeiro evento é entregue assim que o dispositivo transmite uma posição válida\n  no estado de ignição atual.\n- Depois de uma entrega, os pings seguintes são **descartados** até completar 3\n  minutos desde o último envio.\n- Passados os 3 minutos, o próximo ping disponível é entregue e o ciclo recomeça.\n- Uma **mudança de estado da ignição** força o envio imediato, sem esperar o ciclo —\n  é o que garante que a transição entre `position` e `position_sleep` apareça no fluxo.\n\nNa prática, 100 veículos em movimento contínuo geram **no máximo ~33 eventos por\nminuto** (100 ÷ 3), não centenas de pings.\n\n> Se a sua aplicação precisa de rastreamento contínuo, ping a ping, o webhook **não\n> é o canal correto** — use `GET /public/v1/paths`. Webhook é otimizado para eventos\n> discretos.\n\n---\n\nAssine o tipo **`position_sleep`** para receber este evento.\nA Cobli envia este evento como `POST application/json` para a URL cadastrada na\nassinatura, assinado em `X-Cobli-Signature`. Responda `2xx` em até 5 segundos e\ndeduplique por `eventId`.\n",
        "security": [
          {
            "CobliWebhookSignature": []
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Envelope do evento `position_sleep`.",
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/EventEnvelope"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "eventType": {
                        "type": "string",
                        "enum": [
                          "position_sleep"
                        ]
                      },
                      "eventData": {
                        "$ref": "#/components/schemas/PositionEventData"
                      }
                    }
                  }
                ]
              },
              "example": {
                "eventId": "b2c3d4e5-0000-0000-0000-222233334444",
                "eventTime": "2024-03-15T10:00:00Z",
                "eventType": "position_sleep",
                "eventData": {
                  "deviceId": "879797465464874",
                  "vehicleId": "05009b4a-bed3-4431-955a-4c3e80dc6697",
                  "fleetId": "cf3f1990-2ce3-4ed9-85c5-9a528295ecfe",
                  "licensePlate": "ABC1D23",
                  "cobliId": "R875",
                  "latitude": -23.55052,
                  "longitude": -46.633308,
                  "heading": 180,
                  "ignition": "OFF",
                  "odometer": 45245,
                  "numberOfSatellites": 12,
                  "hdop": 0.9,
                  "batteryVoltage": 12480,
                  "connectionType": "FOUR_G_LTE"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/WebhookAck"
          },
          "400": {
            "$ref": "#/components/responses/WebhookRejected"
          },
          "429": {
            "$ref": "#/components/responses/WebhookThrottled"
          },
          "500": {
            "$ref": "#/components/responses/WebhookServerError"
          }
        }
      }
    },
    "alert_driven_over_speed": {
      "post": {
        "tags": [
          "Eventos de Webhook"
        ],
        "operationId": "webhookAlertDrivenOverSpeed",
        "summary": "alert_driven_over_speed — Início de alerta de excesso de velocidade",
        "description": "Disparado no **início** de um alerta de excesso de velocidade, quando o veículo\nultrapassa o limite configurado.\n\n> **Assine o tipo `speed`.** Ele entrega automaticamente tanto\n> `alert_driven_over_speed` quanto `end_alert_driven_over_speed` — os dois eventos são\n> inseparáveis e não podem ser assinados isoladamente.\n\n---\n\nEntregue pela assinatura do tipo **`speed`**.\nA Cobli envia este evento como `POST application/json` para a URL cadastrada na\nassinatura, assinado em `X-Cobli-Signature`. Responda `2xx` em até 5 segundos e\ndeduplique por `eventId`.\n",
        "security": [
          {
            "CobliWebhookSignature": []
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Envelope do evento `alert_driven_over_speed`.",
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/EventEnvelope"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "eventType": {
                        "type": "string",
                        "enum": [
                          "alert_driven_over_speed"
                        ]
                      },
                      "eventData": {
                        "$ref": "#/components/schemas/SpeedAlertStartEventData"
                      }
                    }
                  }
                ]
              },
              "example": {
                "eventId": "c3d4e5f6-0000-0000-0000-333344445555",
                "eventTime": "2024-03-15T14:30:00Z",
                "eventType": "alert_driven_over_speed",
                "eventData": {
                  "deviceId": "879797465464874",
                  "vehicleId": "05009b4a-bed3-4431-955a-4c3e80dc6697",
                  "fleetId": "cf3f1990-2ce3-4ed9-85c5-9a528295ecfe",
                  "licensePlate": "ABC1D23",
                  "cobliId": "R875",
                  "driverId": "d1234567-0000-0000-0000-000000000001",
                  "latitude": -23.55052,
                  "longitude": -46.633308,
                  "speedInKmh": 95,
                  "speedLimitInKmh": 80,
                  "severity": "HIGH",
                  "hdop": 1.2,
                  "batteryVoltage": 12450
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/WebhookAck"
          },
          "400": {
            "$ref": "#/components/responses/WebhookRejected"
          },
          "429": {
            "$ref": "#/components/responses/WebhookThrottled"
          },
          "500": {
            "$ref": "#/components/responses/WebhookServerError"
          }
        }
      }
    },
    "end_alert_driven_over_speed": {
      "post": {
        "tags": [
          "Eventos de Webhook"
        ],
        "operationId": "webhookEndAlertDrivenOverSpeed",
        "summary": "end_alert_driven_over_speed — Fim de alerta de excesso de velocidade",
        "description": "Disparado quando o veículo volta ao limite de velocidade, fechando o\n`alert_driven_over_speed` correspondente e acrescentando a duração total da\ninfração.\n\n> Correlacione o par pelo **`deviceId` + `startTime`**: `startTime` deste evento\n> corresponde ao `eventTime` do `alert_driven_over_speed` que o abriu. Quando o\n> dispositivo não reporta o instante de início, a Cobli o deriva de\n> `eventTime - durationAboveInMillis`, e aí o valor pode diferir em milissegundos.\n\n---\n\nEntregue pela assinatura do tipo **`speed`**.\nA Cobli envia este evento como `POST application/json` para a URL cadastrada na\nassinatura, assinado em `X-Cobli-Signature`. Responda `2xx` em até 5 segundos e\ndeduplique por `eventId`.\n",
        "security": [
          {
            "CobliWebhookSignature": []
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Envelope do evento `end_alert_driven_over_speed`.",
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/EventEnvelope"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "eventType": {
                        "type": "string",
                        "enum": [
                          "end_alert_driven_over_speed"
                        ]
                      },
                      "eventData": {
                        "$ref": "#/components/schemas/SpeedAlertEndEventData"
                      }
                    }
                  }
                ]
              },
              "example": {
                "eventId": "d4e5f6a7-0000-0000-0000-444455556666",
                "eventTime": "2024-03-15T14:31:30Z",
                "eventType": "end_alert_driven_over_speed",
                "eventData": {
                  "deviceId": "879797465464874",
                  "vehicleId": "05009b4a-bed3-4431-955a-4c3e80dc6697",
                  "fleetId": "cf3f1990-2ce3-4ed9-85c5-9a528295ecfe",
                  "licensePlate": "ABC1D23",
                  "cobliId": "R875",
                  "driverId": "d1234567-0000-0000-0000-000000000001",
                  "latitude": -23.5521,
                  "longitude": -46.6345,
                  "speedInKmh": 78,
                  "speedLimitInKmh": 80,
                  "severity": "HIGH",
                  "startTime": "2024-03-15T14:30:00Z",
                  "durationAboveInMillis": 90000,
                  "hdop": 1.2,
                  "batteryVoltage": 12450
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/WebhookAck"
          },
          "400": {
            "$ref": "#/components/responses/WebhookRejected"
          },
          "429": {
            "$ref": "#/components/responses/WebhookThrottled"
          },
          "500": {
            "$ref": "#/components/responses/WebhookServerError"
          }
        }
      }
    },
    "battery_external_low": {
      "post": {
        "tags": [
          "Eventos de Webhook"
        ],
        "operationId": "webhookBatteryExternalLow",
        "summary": "battery_external_low — Tensão da bateria externa abaixo do threshold",
        "description": "Disparado quando a **tensão média** da bateria externa cai abaixo do threshold\nconfigurado para a frota. A média evita disparos espúrios em quedas instantâneas,\ncomo a partida do motor.\n\nO threshold aplicado vem em `batteryVoltageThresholdMv` e depende de `voltageRegime`:\nfrotas mistas têm um threshold para 12 V (`LIGHT`) e outro para 24 V (`HEAVY`).\n\n> **Janela de 4 horas por dispositivo.** Depois de um `battery_external_low`, novas\n> quedas abaixo do threshold no mesmo dispositivo são silenciadas por 4 h. Ausência\n> de evento nesse intervalo não significa que a tensão se recuperou.\n\n---\n\nAssine o tipo **`battery_external_low`** para receber este evento.\nA Cobli envia este evento como `POST application/json` para a URL cadastrada na\nassinatura, assinado em `X-Cobli-Signature`. Responda `2xx` em até 5 segundos e\ndeduplique por `eventId`.\n",
        "security": [
          {
            "CobliWebhookSignature": []
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Envelope do evento `battery_external_low`.",
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/EventEnvelope"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "eventType": {
                        "type": "string",
                        "enum": [
                          "battery_external_low"
                        ]
                      },
                      "eventData": {
                        "$ref": "#/components/schemas/BatteryExternalLowEventData"
                      }
                    }
                  }
                ]
              },
              "example": {
                "eventId": "e5f6a7b8-0000-0000-0000-555566667777",
                "eventTime": "2024-03-15T22:10:00Z",
                "eventType": "battery_external_low",
                "eventData": {
                  "deviceId": "879797465464874",
                  "vehicleId": "05009b4a-bed3-4431-955a-4c3e80dc6697",
                  "fleetId": "cf3f1990-2ce3-4ed9-85c5-9a528295ecfe",
                  "licensePlate": "ABC1D23",
                  "cobliId": "R875",
                  "latitude": -23.55052,
                  "longitude": -46.633308,
                  "heading": 0,
                  "speedInKmh": 8.2,
                  "ignition": "OFF",
                  "odometer": 45230.5,
                  "batteryVoltage": 11200,
                  "batteryVoltageThresholdMv": 11500,
                  "voltageRegime": "LIGHT",
                  "connectionType": "FOUR_G_LTE"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/WebhookAck"
          },
          "400": {
            "$ref": "#/components/responses/WebhookRejected"
          },
          "429": {
            "$ref": "#/components/responses/WebhookThrottled"
          },
          "500": {
            "$ref": "#/components/responses/WebhookServerError"
          }
        }
      }
    },
    "battery_external_disconnected": {
      "post": {
        "tags": [
          "Eventos de Webhook"
        ],
        "operationId": "webhookBatteryExternalDisconnected",
        "summary": "battery_external_disconnected — Bateria externa desconectada",
        "description": "Disparado quando a bateria externa é **desconectada** do dispositivo.\n\nUm `battery_external_disconnected` sem `battery_external_reconnected` na sequência\ncostuma indicar violação do equipamento ou manutenção elétrica em curso.\n\n---\n\nAssine o tipo **`battery_external_disconnected`** para receber este evento.\nA Cobli envia este evento como `POST application/json` para a URL cadastrada na\nassinatura, assinado em `X-Cobli-Signature`. Responda `2xx` em até 5 segundos e\ndeduplique por `eventId`.\n",
        "security": [
          {
            "CobliWebhookSignature": []
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Envelope do evento `battery_external_disconnected`.",
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/EventEnvelope"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "eventType": {
                        "type": "string",
                        "enum": [
                          "battery_external_disconnected"
                        ]
                      },
                      "eventData": {
                        "$ref": "#/components/schemas/BatteryExternalConnectionEventData"
                      }
                    }
                  }
                ]
              },
              "example": {
                "eventId": "f6a7b8c9-0000-0000-0000-666677778888",
                "eventTime": "2024-03-15T22:15:00Z",
                "eventType": "battery_external_disconnected",
                "eventData": {
                  "deviceId": "879797465464874",
                  "vehicleId": "05009b4a-bed3-4431-955a-4c3e80dc6697",
                  "fleetId": "cf3f1990-2ce3-4ed9-85c5-9a528295ecfe",
                  "licensePlate": "ABC1D23",
                  "cobliId": "R875",
                  "latitude": -23.55052,
                  "longitude": -46.633308,
                  "heading": 0,
                  "speedInKmh": 8.2,
                  "ignition": "OFF",
                  "odometer": 45230.5,
                  "batteryVoltage": 11800,
                  "connectionType": "FOUR_G_LTE"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/WebhookAck"
          },
          "400": {
            "$ref": "#/components/responses/WebhookRejected"
          },
          "429": {
            "$ref": "#/components/responses/WebhookThrottled"
          },
          "500": {
            "$ref": "#/components/responses/WebhookServerError"
          }
        }
      }
    },
    "battery_external_reconnected": {
      "post": {
        "tags": [
          "Eventos de Webhook"
        ],
        "operationId": "webhookBatteryExternalReconnected",
        "summary": "battery_external_reconnected — Bateria externa reconectada",
        "description": "Disparado quando a bateria externa é **reconectada** do dispositivo.\n\nFecha o ciclo aberto por `battery_external_disconnected`. `batteryVoltage` traz a\ntensão lida na reconexão.\n\n---\n\nAssine o tipo **`battery_external_reconnected`** para receber este evento.\nA Cobli envia este evento como `POST application/json` para a URL cadastrada na\nassinatura, assinado em `X-Cobli-Signature`. Responda `2xx` em até 5 segundos e\ndeduplique por `eventId`.\n",
        "security": [
          {
            "CobliWebhookSignature": []
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Envelope do evento `battery_external_reconnected`.",
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/EventEnvelope"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "eventType": {
                        "type": "string",
                        "enum": [
                          "battery_external_reconnected"
                        ]
                      },
                      "eventData": {
                        "$ref": "#/components/schemas/BatteryExternalConnectionEventData"
                      }
                    }
                  }
                ]
              },
              "example": {
                "eventId": "a7b8c9d0-0000-0000-0000-777788889999",
                "eventTime": "2024-03-15T22:20:00Z",
                "eventType": "battery_external_reconnected",
                "eventData": {
                  "deviceId": "879797465464874",
                  "vehicleId": "05009b4a-bed3-4431-955a-4c3e80dc6697",
                  "fleetId": "cf3f1990-2ce3-4ed9-85c5-9a528295ecfe",
                  "licensePlate": "ABC1D23",
                  "cobliId": "R875",
                  "latitude": -23.55052,
                  "longitude": -46.633308,
                  "heading": 0,
                  "speedInKmh": 8.2,
                  "ignition": "OFF",
                  "odometer": 45230.5,
                  "batteryVoltage": 12350,
                  "connectionType": "FOUR_G_LTE"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/WebhookAck"
          },
          "400": {
            "$ref": "#/components/responses/WebhookRejected"
          },
          "429": {
            "$ref": "#/components/responses/WebhookThrottled"
          },
          "500": {
            "$ref": "#/components/responses/WebhookServerError"
          }
        }
      }
    },
    "hard_break": {
      "post": {
        "tags": [
          "Eventos de Webhook"
        ],
        "operationId": "webhookHardBreak",
        "summary": "hard_break — Frenagem brusca detectada pela câmera",
        "description": "Disparado quando a câmera integrada Cobli detecta **frenagem brusca**.\n\nOs 11 tipos de evento de câmera compartilham a mesma estrutura de payload — o\n`eventType` identifica o comportamento detectado.\n\n> **Disponibilidade.** Apenas para frotas com dispositivos de câmera integrada\n> Cobli, e a oferta de cada tipo depende do modelo instalado.\n\n> `rpm` e `fuelLevel` **nunca** estão presentes: a câmera não acessa o barramento\n> CAN. `odometer` aparece quando há odômetro inicial cadastrado no veículo.\n\n---\n\nAssine o tipo **`hard_break`** para receber este evento.\nA Cobli envia este evento como `POST application/json` para a URL cadastrada na\nassinatura, assinado em `X-Cobli-Signature`. Responda `2xx` em até 5 segundos e\ndeduplique por `eventId`.\n",
        "security": [
          {
            "CobliWebhookSignature": []
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Envelope do evento `hard_break`.",
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/EventEnvelope"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "eventType": {
                        "type": "string",
                        "enum": [
                          "hard_break"
                        ]
                      },
                      "eventData": {
                        "$ref": "#/components/schemas/CameraEventData"
                      }
                    }
                  }
                ]
              },
              "example": {
                "eventId": "7decdf99-283d-4c70-9b95-a3b3f896e9b9",
                "eventTime": "2024-03-15T10:23:07Z",
                "eventType": "hard_break",
                "eventData": {
                  "deviceId": "879797465464874",
                  "vehicleId": "05009b4a-bed3-4431-955a-4c3e80dc6697",
                  "fleetId": "cf3f1990-2ce3-4ed9-85c5-9a528295ecfe",
                  "licensePlate": "ABC1D23",
                  "cobliId": "R875",
                  "driverId": "d1234567-0000-0000-0000-000000000001",
                  "latitude": -23.55052,
                  "longitude": -46.633308,
                  "speedInKmh": 72.5,
                  "heading": 180,
                  "ignition": "ON",
                  "batteryVoltage": 12800,
                  "numberOfSatellites": 12,
                  "hdop": 0.8,
                  "connectionType": "FOUR_G_LTE"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/WebhookAck"
          },
          "400": {
            "$ref": "#/components/responses/WebhookRejected"
          },
          "429": {
            "$ref": "#/components/responses/WebhookThrottled"
          },
          "500": {
            "$ref": "#/components/responses/WebhookServerError"
          }
        }
      }
    },
    "fast_acceleration": {
      "post": {
        "tags": [
          "Eventos de Webhook"
        ],
        "operationId": "webhookFastAcceleration",
        "summary": "fast_acceleration — Aceleração brusca detectada pela câmera",
        "description": "Disparado quando a câmera integrada Cobli detecta **aceleração brusca**.\n\nOs 11 tipos de evento de câmera compartilham a mesma estrutura de payload — o\n`eventType` identifica o comportamento detectado.\n\n> **Disponibilidade.** Apenas para frotas com dispositivos de câmera integrada\n> Cobli, e a oferta de cada tipo depende do modelo instalado.\n\n> `rpm` e `fuelLevel` **nunca** estão presentes: a câmera não acessa o barramento\n> CAN. `odometer` aparece quando há odômetro inicial cadastrado no veículo.\n\n---\n\nAssine o tipo **`fast_acceleration`** para receber este evento.\nA Cobli envia este evento como `POST application/json` para a URL cadastrada na\nassinatura, assinado em `X-Cobli-Signature`. Responda `2xx` em até 5 segundos e\ndeduplique por `eventId`.\n",
        "security": [
          {
            "CobliWebhookSignature": []
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Envelope do evento `fast_acceleration`.",
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/EventEnvelope"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "eventType": {
                        "type": "string",
                        "enum": [
                          "fast_acceleration"
                        ]
                      },
                      "eventData": {
                        "$ref": "#/components/schemas/CameraEventData"
                      }
                    }
                  }
                ]
              },
              "example": {
                "eventId": "7decdf99-283d-4c70-9b95-a3b3f896e9b9",
                "eventTime": "2024-03-15T10:23:07Z",
                "eventType": "fast_acceleration",
                "eventData": {
                  "deviceId": "879797465464874",
                  "vehicleId": "05009b4a-bed3-4431-955a-4c3e80dc6697",
                  "fleetId": "cf3f1990-2ce3-4ed9-85c5-9a528295ecfe",
                  "licensePlate": "ABC1D23",
                  "cobliId": "R875",
                  "driverId": "d1234567-0000-0000-0000-000000000001",
                  "latitude": -23.55052,
                  "longitude": -46.633308,
                  "speedInKmh": 72.5,
                  "heading": 180,
                  "ignition": "ON",
                  "batteryVoltage": 12800,
                  "numberOfSatellites": 12,
                  "hdop": 0.8,
                  "connectionType": "FOUR_G_LTE"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/WebhookAck"
          },
          "400": {
            "$ref": "#/components/responses/WebhookRejected"
          },
          "429": {
            "$ref": "#/components/responses/WebhookThrottled"
          },
          "500": {
            "$ref": "#/components/responses/WebhookServerError"
          }
        }
      }
    },
    "speedy_turn": {
      "post": {
        "tags": [
          "Eventos de Webhook"
        ],
        "operationId": "webhookSpeedyTurn",
        "summary": "speedy_turn — Curva acentuada detectada pela câmera",
        "description": "Disparado quando a câmera integrada Cobli detecta **curva acentuada**.\n\nOs 11 tipos de evento de câmera compartilham a mesma estrutura de payload — o\n`eventType` identifica o comportamento detectado.\n\n> **Disponibilidade.** Apenas para frotas com dispositivos de câmera integrada\n> Cobli, e a oferta de cada tipo depende do modelo instalado.\n\n> `rpm` e `fuelLevel` **nunca** estão presentes: a câmera não acessa o barramento\n> CAN. `odometer` aparece quando há odômetro inicial cadastrado no veículo.\n\n---\n\nAssine o tipo **`speedy_turn`** para receber este evento.\nA Cobli envia este evento como `POST application/json` para a URL cadastrada na\nassinatura, assinado em `X-Cobli-Signature`. Responda `2xx` em até 5 segundos e\ndeduplique por `eventId`.\n",
        "security": [
          {
            "CobliWebhookSignature": []
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Envelope do evento `speedy_turn`.",
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/EventEnvelope"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "eventType": {
                        "type": "string",
                        "enum": [
                          "speedy_turn"
                        ]
                      },
                      "eventData": {
                        "$ref": "#/components/schemas/CameraEventData"
                      }
                    }
                  }
                ]
              },
              "example": {
                "eventId": "7decdf99-283d-4c70-9b95-a3b3f896e9b9",
                "eventTime": "2024-03-15T10:23:07Z",
                "eventType": "speedy_turn",
                "eventData": {
                  "deviceId": "879797465464874",
                  "vehicleId": "05009b4a-bed3-4431-955a-4c3e80dc6697",
                  "fleetId": "cf3f1990-2ce3-4ed9-85c5-9a528295ecfe",
                  "licensePlate": "ABC1D23",
                  "cobliId": "R875",
                  "driverId": "d1234567-0000-0000-0000-000000000001",
                  "latitude": -23.55052,
                  "longitude": -46.633308,
                  "speedInKmh": 72.5,
                  "heading": 180,
                  "ignition": "ON",
                  "batteryVoltage": 12800,
                  "numberOfSatellites": 12,
                  "hdop": 0.8,
                  "connectionType": "FOUR_G_LTE"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/WebhookAck"
          },
          "400": {
            "$ref": "#/components/responses/WebhookRejected"
          },
          "429": {
            "$ref": "#/components/responses/WebhookThrottled"
          },
          "500": {
            "$ref": "#/components/responses/WebhookServerError"
          }
        }
      }
    },
    "tailgating": {
      "post": {
        "tags": [
          "Eventos de Webhook"
        ],
        "operationId": "webhookTailgating",
        "summary": "tailgating — Seguimento próximo detectado pela câmera",
        "description": "Disparado quando a câmera integrada Cobli detecta **seguimento próximo do veículo à frente**.\n\nOs 11 tipos de evento de câmera compartilham a mesma estrutura de payload — o\n`eventType` identifica o comportamento detectado.\n\n> **Disponibilidade.** Apenas para frotas com dispositivos de câmera integrada\n> Cobli, e a oferta de cada tipo depende do modelo instalado.\n\n> `rpm` e `fuelLevel` **nunca** estão presentes: a câmera não acessa o barramento\n> CAN. `odometer` aparece quando há odômetro inicial cadastrado no veículo.\n\n---\n\nAssine o tipo **`tailgating`** para receber este evento.\nA Cobli envia este evento como `POST application/json` para a URL cadastrada na\nassinatura, assinado em `X-Cobli-Signature`. Responda `2xx` em até 5 segundos e\ndeduplique por `eventId`.\n",
        "security": [
          {
            "CobliWebhookSignature": []
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Envelope do evento `tailgating`.",
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/EventEnvelope"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "eventType": {
                        "type": "string",
                        "enum": [
                          "tailgating"
                        ]
                      },
                      "eventData": {
                        "$ref": "#/components/schemas/CameraEventData"
                      }
                    }
                  }
                ]
              },
              "example": {
                "eventId": "7decdf99-283d-4c70-9b95-a3b3f896e9b9",
                "eventTime": "2024-03-15T10:23:07Z",
                "eventType": "tailgating",
                "eventData": {
                  "deviceId": "879797465464874",
                  "vehicleId": "05009b4a-bed3-4431-955a-4c3e80dc6697",
                  "fleetId": "cf3f1990-2ce3-4ed9-85c5-9a528295ecfe",
                  "licensePlate": "ABC1D23",
                  "cobliId": "R875",
                  "driverId": "d1234567-0000-0000-0000-000000000001",
                  "latitude": -23.55052,
                  "longitude": -46.633308,
                  "speedInKmh": 72.5,
                  "heading": 180,
                  "ignition": "ON",
                  "batteryVoltage": 12800,
                  "numberOfSatellites": 12,
                  "hdop": 0.8,
                  "connectionType": "FOUR_G_LTE"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/WebhookAck"
          },
          "400": {
            "$ref": "#/components/responses/WebhookRejected"
          },
          "429": {
            "$ref": "#/components/responses/WebhookThrottled"
          },
          "500": {
            "$ref": "#/components/responses/WebhookServerError"
          }
        }
      }
    },
    "front_collision_warning": {
      "post": {
        "tags": [
          "Eventos de Webhook"
        ],
        "operationId": "webhookFrontCollisionWarning",
        "summary": "front_collision_warning — Aviso de colisão frontal detectado pela câmera",
        "description": "Disparado quando a câmera integrada Cobli detecta **risco de colisão frontal**.\n\nOs 11 tipos de evento de câmera compartilham a mesma estrutura de payload — o\n`eventType` identifica o comportamento detectado.\n\n> **Disponibilidade.** Apenas para frotas com dispositivos de câmera integrada\n> Cobli, e a oferta de cada tipo depende do modelo instalado.\n\n> `rpm` e `fuelLevel` **nunca** estão presentes: a câmera não acessa o barramento\n> CAN. `odometer` aparece quando há odômetro inicial cadastrado no veículo.\n\n---\n\nAssine o tipo **`front_collision_warning`** para receber este evento.\nA Cobli envia este evento como `POST application/json` para a URL cadastrada na\nassinatura, assinado em `X-Cobli-Signature`. Responda `2xx` em até 5 segundos e\ndeduplique por `eventId`.\n",
        "security": [
          {
            "CobliWebhookSignature": []
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Envelope do evento `front_collision_warning`.",
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/EventEnvelope"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "eventType": {
                        "type": "string",
                        "enum": [
                          "front_collision_warning"
                        ]
                      },
                      "eventData": {
                        "$ref": "#/components/schemas/CameraEventData"
                      }
                    }
                  }
                ]
              },
              "example": {
                "eventId": "7decdf99-283d-4c70-9b95-a3b3f896e9b9",
                "eventTime": "2024-03-15T10:23:07Z",
                "eventType": "front_collision_warning",
                "eventData": {
                  "deviceId": "879797465464874",
                  "vehicleId": "05009b4a-bed3-4431-955a-4c3e80dc6697",
                  "fleetId": "cf3f1990-2ce3-4ed9-85c5-9a528295ecfe",
                  "licensePlate": "ABC1D23",
                  "cobliId": "R875",
                  "driverId": "d1234567-0000-0000-0000-000000000001",
                  "latitude": -23.55052,
                  "longitude": -46.633308,
                  "speedInKmh": 72.5,
                  "heading": 180,
                  "ignition": "ON",
                  "batteryVoltage": 12800,
                  "numberOfSatellites": 12,
                  "hdop": 0.8,
                  "connectionType": "FOUR_G_LTE"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/WebhookAck"
          },
          "400": {
            "$ref": "#/components/responses/WebhookRejected"
          },
          "429": {
            "$ref": "#/components/responses/WebhookThrottled"
          },
          "500": {
            "$ref": "#/components/responses/WebhookServerError"
          }
        }
      }
    },
    "distracted_driving": {
      "post": {
        "tags": [
          "Eventos de Webhook"
        ],
        "operationId": "webhookDistractedDriving",
        "summary": "distracted_driving — Distração ao volante detectada pela câmera",
        "description": "Disparado quando a câmera integrada Cobli detecta **distração do motorista ao volante**.\n\nOs 11 tipos de evento de câmera compartilham a mesma estrutura de payload — o\n`eventType` identifica o comportamento detectado.\n\n> **Disponibilidade.** Apenas para frotas com dispositivos de câmera integrada\n> Cobli, e a oferta de cada tipo depende do modelo instalado.\n\n> `rpm` e `fuelLevel` **nunca** estão presentes: a câmera não acessa o barramento\n> CAN. `odometer` aparece quando há odômetro inicial cadastrado no veículo.\n\n---\n\nAssine o tipo **`distracted_driving`** para receber este evento.\nA Cobli envia este evento como `POST application/json` para a URL cadastrada na\nassinatura, assinado em `X-Cobli-Signature`. Responda `2xx` em até 5 segundos e\ndeduplique por `eventId`.\n",
        "security": [
          {
            "CobliWebhookSignature": []
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Envelope do evento `distracted_driving`.",
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/EventEnvelope"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "eventType": {
                        "type": "string",
                        "enum": [
                          "distracted_driving"
                        ]
                      },
                      "eventData": {
                        "$ref": "#/components/schemas/CameraEventData"
                      }
                    }
                  }
                ]
              },
              "example": {
                "eventId": "7decdf99-283d-4c70-9b95-a3b3f896e9b9",
                "eventTime": "2024-03-15T10:23:07Z",
                "eventType": "distracted_driving",
                "eventData": {
                  "deviceId": "879797465464874",
                  "vehicleId": "05009b4a-bed3-4431-955a-4c3e80dc6697",
                  "fleetId": "cf3f1990-2ce3-4ed9-85c5-9a528295ecfe",
                  "licensePlate": "ABC1D23",
                  "cobliId": "R875",
                  "driverId": "d1234567-0000-0000-0000-000000000001",
                  "latitude": -23.55052,
                  "longitude": -46.633308,
                  "speedInKmh": 72.5,
                  "heading": 180,
                  "ignition": "ON",
                  "batteryVoltage": 12800,
                  "numberOfSatellites": 12,
                  "hdop": 0.8,
                  "connectionType": "FOUR_G_LTE"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/WebhookAck"
          },
          "400": {
            "$ref": "#/components/responses/WebhookRejected"
          },
          "429": {
            "$ref": "#/components/responses/WebhookThrottled"
          },
          "500": {
            "$ref": "#/components/responses/WebhookServerError"
          }
        }
      }
    },
    "eyes_closed": {
      "post": {
        "tags": [
          "Eventos de Webhook"
        ],
        "operationId": "webhookEyesClosed",
        "summary": "eyes_closed — Olhos fechados detectados pela câmera",
        "description": "Disparado quando a câmera integrada Cobli detecta **olhos fechados do motorista**.\n\nOs 11 tipos de evento de câmera compartilham a mesma estrutura de payload — o\n`eventType` identifica o comportamento detectado.\n\n> **Disponibilidade.** Apenas para frotas com dispositivos de câmera integrada\n> Cobli, e a oferta de cada tipo depende do modelo instalado.\n\n> `rpm` e `fuelLevel` **nunca** estão presentes: a câmera não acessa o barramento\n> CAN. `odometer` aparece quando há odômetro inicial cadastrado no veículo.\n\n---\n\nAssine o tipo **`eyes_closed`** para receber este evento.\nA Cobli envia este evento como `POST application/json` para a URL cadastrada na\nassinatura, assinado em `X-Cobli-Signature`. Responda `2xx` em até 5 segundos e\ndeduplique por `eventId`.\n",
        "security": [
          {
            "CobliWebhookSignature": []
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Envelope do evento `eyes_closed`.",
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/EventEnvelope"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "eventType": {
                        "type": "string",
                        "enum": [
                          "eyes_closed"
                        ]
                      },
                      "eventData": {
                        "$ref": "#/components/schemas/CameraEventData"
                      }
                    }
                  }
                ]
              },
              "example": {
                "eventId": "7decdf99-283d-4c70-9b95-a3b3f896e9b9",
                "eventTime": "2024-03-15T10:23:07Z",
                "eventType": "eyes_closed",
                "eventData": {
                  "deviceId": "879797465464874",
                  "vehicleId": "05009b4a-bed3-4431-955a-4c3e80dc6697",
                  "fleetId": "cf3f1990-2ce3-4ed9-85c5-9a528295ecfe",
                  "licensePlate": "ABC1D23",
                  "cobliId": "R875",
                  "driverId": "d1234567-0000-0000-0000-000000000001",
                  "latitude": -23.55052,
                  "longitude": -46.633308,
                  "speedInKmh": 72.5,
                  "heading": 180,
                  "ignition": "ON",
                  "batteryVoltage": 12800,
                  "numberOfSatellites": 12,
                  "hdop": 0.8,
                  "connectionType": "FOUR_G_LTE"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/WebhookAck"
          },
          "400": {
            "$ref": "#/components/responses/WebhookRejected"
          },
          "429": {
            "$ref": "#/components/responses/WebhookThrottled"
          },
          "500": {
            "$ref": "#/components/responses/WebhookServerError"
          }
        }
      }
    },
    "phone_usage": {
      "post": {
        "tags": [
          "Eventos de Webhook"
        ],
        "operationId": "webhookPhoneUsage",
        "summary": "phone_usage — Uso de celular detectado pela câmera",
        "description": "Disparado quando a câmera integrada Cobli detecta **uso de celular ao volante**.\n\nOs 11 tipos de evento de câmera compartilham a mesma estrutura de payload — o\n`eventType` identifica o comportamento detectado.\n\n> **Disponibilidade.** Apenas para frotas com dispositivos de câmera integrada\n> Cobli, e a oferta de cada tipo depende do modelo instalado.\n\n> `rpm` e `fuelLevel` **nunca** estão presentes: a câmera não acessa o barramento\n> CAN. `odometer` aparece quando há odômetro inicial cadastrado no veículo.\n\n---\n\nAssine o tipo **`phone_usage`** para receber este evento.\nA Cobli envia este evento como `POST application/json` para a URL cadastrada na\nassinatura, assinado em `X-Cobli-Signature`. Responda `2xx` em até 5 segundos e\ndeduplique por `eventId`.\n",
        "security": [
          {
            "CobliWebhookSignature": []
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Envelope do evento `phone_usage`.",
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/EventEnvelope"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "eventType": {
                        "type": "string",
                        "enum": [
                          "phone_usage"
                        ]
                      },
                      "eventData": {
                        "$ref": "#/components/schemas/CameraEventData"
                      }
                    }
                  }
                ]
              },
              "example": {
                "eventId": "7decdf99-283d-4c70-9b95-a3b3f896e9b9",
                "eventTime": "2024-03-15T10:23:07Z",
                "eventType": "phone_usage",
                "eventData": {
                  "deviceId": "879797465464874",
                  "vehicleId": "05009b4a-bed3-4431-955a-4c3e80dc6697",
                  "fleetId": "cf3f1990-2ce3-4ed9-85c5-9a528295ecfe",
                  "licensePlate": "ABC1D23",
                  "cobliId": "R875",
                  "driverId": "d1234567-0000-0000-0000-000000000001",
                  "latitude": -23.55052,
                  "longitude": -46.633308,
                  "speedInKmh": 72.5,
                  "heading": 180,
                  "ignition": "ON",
                  "batteryVoltage": 12800,
                  "numberOfSatellites": 12,
                  "hdop": 0.8,
                  "connectionType": "FOUR_G_LTE"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/WebhookAck"
          },
          "400": {
            "$ref": "#/components/responses/WebhookRejected"
          },
          "429": {
            "$ref": "#/components/responses/WebhookThrottled"
          },
          "500": {
            "$ref": "#/components/responses/WebhookServerError"
          }
        }
      }
    },
    "smoking": {
      "post": {
        "tags": [
          "Eventos de Webhook"
        ],
        "operationId": "webhookSmoking",
        "summary": "smoking — Uso de cigarro detectado pela câmera",
        "description": "Disparado quando a câmera integrada Cobli detecta **uso de cigarro na cabine**.\n\nOs 11 tipos de evento de câmera compartilham a mesma estrutura de payload — o\n`eventType` identifica o comportamento detectado.\n\n> **Disponibilidade.** Apenas para frotas com dispositivos de câmera integrada\n> Cobli, e a oferta de cada tipo depende do modelo instalado.\n\n> `rpm` e `fuelLevel` **nunca** estão presentes: a câmera não acessa o barramento\n> CAN. `odometer` aparece quando há odômetro inicial cadastrado no veículo.\n\n---\n\nAssine o tipo **`smoking`** para receber este evento.\nA Cobli envia este evento como `POST application/json` para a URL cadastrada na\nassinatura, assinado em `X-Cobli-Signature`. Responda `2xx` em até 5 segundos e\ndeduplique por `eventId`.\n",
        "security": [
          {
            "CobliWebhookSignature": []
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Envelope do evento `smoking`.",
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/EventEnvelope"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "eventType": {
                        "type": "string",
                        "enum": [
                          "smoking"
                        ]
                      },
                      "eventData": {
                        "$ref": "#/components/schemas/CameraEventData"
                      }
                    }
                  }
                ]
              },
              "example": {
                "eventId": "7decdf99-283d-4c70-9b95-a3b3f896e9b9",
                "eventTime": "2024-03-15T10:23:07Z",
                "eventType": "smoking",
                "eventData": {
                  "deviceId": "879797465464874",
                  "vehicleId": "05009b4a-bed3-4431-955a-4c3e80dc6697",
                  "fleetId": "cf3f1990-2ce3-4ed9-85c5-9a528295ecfe",
                  "licensePlate": "ABC1D23",
                  "cobliId": "R875",
                  "driverId": "d1234567-0000-0000-0000-000000000001",
                  "latitude": -23.55052,
                  "longitude": -46.633308,
                  "speedInKmh": 72.5,
                  "heading": 180,
                  "ignition": "ON",
                  "batteryVoltage": 12800,
                  "numberOfSatellites": 12,
                  "hdop": 0.8,
                  "connectionType": "FOUR_G_LTE"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/WebhookAck"
          },
          "400": {
            "$ref": "#/components/responses/WebhookRejected"
          },
          "429": {
            "$ref": "#/components/responses/WebhookThrottled"
          },
          "500": {
            "$ref": "#/components/responses/WebhookServerError"
          }
        }
      }
    },
    "yawn": {
      "post": {
        "tags": [
          "Eventos de Webhook"
        ],
        "operationId": "webhookYawn",
        "summary": "yawn — Bocejo detectado pela câmera",
        "description": "Disparado quando a câmera integrada Cobli detecta **bocejo do motorista**.\n\nOs 11 tipos de evento de câmera compartilham a mesma estrutura de payload — o\n`eventType` identifica o comportamento detectado.\n\n> **Disponibilidade.** Apenas para frotas com dispositivos de câmera integrada\n> Cobli, e a oferta de cada tipo depende do modelo instalado.\n\n> `rpm` e `fuelLevel` **nunca** estão presentes: a câmera não acessa o barramento\n> CAN. `odometer` aparece quando há odômetro inicial cadastrado no veículo.\n\n---\n\nAssine o tipo **`yawn`** para receber este evento.\nA Cobli envia este evento como `POST application/json` para a URL cadastrada na\nassinatura, assinado em `X-Cobli-Signature`. Responda `2xx` em até 5 segundos e\ndeduplique por `eventId`.\n",
        "security": [
          {
            "CobliWebhookSignature": []
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Envelope do evento `yawn`.",
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/EventEnvelope"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "eventType": {
                        "type": "string",
                        "enum": [
                          "yawn"
                        ]
                      },
                      "eventData": {
                        "$ref": "#/components/schemas/CameraEventData"
                      }
                    }
                  }
                ]
              },
              "example": {
                "eventId": "7decdf99-283d-4c70-9b95-a3b3f896e9b9",
                "eventTime": "2024-03-15T10:23:07Z",
                "eventType": "yawn",
                "eventData": {
                  "deviceId": "879797465464874",
                  "vehicleId": "05009b4a-bed3-4431-955a-4c3e80dc6697",
                  "fleetId": "cf3f1990-2ce3-4ed9-85c5-9a528295ecfe",
                  "licensePlate": "ABC1D23",
                  "cobliId": "R875",
                  "driverId": "d1234567-0000-0000-0000-000000000001",
                  "latitude": -23.55052,
                  "longitude": -46.633308,
                  "speedInKmh": 72.5,
                  "heading": 180,
                  "ignition": "ON",
                  "batteryVoltage": 12800,
                  "numberOfSatellites": 12,
                  "hdop": 0.8,
                  "connectionType": "FOUR_G_LTE"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/WebhookAck"
          },
          "400": {
            "$ref": "#/components/responses/WebhookRejected"
          },
          "429": {
            "$ref": "#/components/responses/WebhookThrottled"
          },
          "500": {
            "$ref": "#/components/responses/WebhookServerError"
          }
        }
      }
    },
    "sos": {
      "post": {
        "tags": [
          "Eventos de Webhook"
        ],
        "operationId": "webhookSos",
        "summary": "sos — Sinal SOS acionado pelo motorista",
        "description": "Disparado quando a câmera integrada Cobli detecta **acionamento do botão de SOS pelo motorista**.\n\nOs 11 tipos de evento de câmera compartilham a mesma estrutura de payload — o\n`eventType` identifica o comportamento detectado.\n\n> **Disponibilidade.** Apenas para frotas com dispositivos de câmera integrada\n> Cobli, e a oferta de cada tipo depende do modelo instalado.\n\n> `rpm` e `fuelLevel` **nunca** estão presentes: a câmera não acessa o barramento\n> CAN. `odometer` aparece quando há odômetro inicial cadastrado no veículo.\n\n---\n\nAssine o tipo **`sos`** para receber este evento.\nA Cobli envia este evento como `POST application/json` para a URL cadastrada na\nassinatura, assinado em `X-Cobli-Signature`. Responda `2xx` em até 5 segundos e\ndeduplique por `eventId`.\n",
        "security": [
          {
            "CobliWebhookSignature": []
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Envelope do evento `sos`.",
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/EventEnvelope"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "eventType": {
                        "type": "string",
                        "enum": [
                          "sos"
                        ]
                      },
                      "eventData": {
                        "$ref": "#/components/schemas/CameraEventData"
                      }
                    }
                  }
                ]
              },
              "example": {
                "eventId": "7decdf99-283d-4c70-9b95-a3b3f896e9b9",
                "eventTime": "2024-03-15T10:23:07Z",
                "eventType": "sos",
                "eventData": {
                  "deviceId": "879797465464874",
                  "vehicleId": "05009b4a-bed3-4431-955a-4c3e80dc6697",
                  "fleetId": "cf3f1990-2ce3-4ed9-85c5-9a528295ecfe",
                  "licensePlate": "ABC1D23",
                  "cobliId": "R875",
                  "driverId": "d1234567-0000-0000-0000-000000000001",
                  "latitude": -23.55052,
                  "longitude": -46.633308,
                  "speedInKmh": 72.5,
                  "heading": 180,
                  "ignition": "ON",
                  "batteryVoltage": 12800,
                  "numberOfSatellites": 12,
                  "hdop": 0.8,
                  "connectionType": "FOUR_G_LTE"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/WebhookAck"
          },
          "400": {
            "$ref": "#/components/responses/WebhookRejected"
          },
          "429": {
            "$ref": "#/components/responses/WebhookThrottled"
          },
          "500": {
            "$ref": "#/components/responses/WebhookServerError"
          }
        }
      }
    },
    "route_started": {
      "post": {
        "tags": [
          "Eventos de Webhook"
        ],
        "operationId": "webhookRouteStarted",
        "summary": "route_started — Motorista iniciou a rota",
        "description": "Disparado quando o motorista **inicia** a rota no aplicativo.\n\nTraz apenas o bloco `route`; `route.outcome` ainda não existe neste momento.\n\n> **Assine o grupo `routes`** — plural, literalmente `\"routes\"` em `event_types`. É um\n> grupo de **composição fechada**: entrega exatamente `route_started` e `route_finished`,\n> e um tipo novo do catálogo **não** passa a ser entregue sem que você atualize a\n> assinatura.\n\n> **`deviceId` e `vehicleId` podem não vir.** O contrato os declara opcionais e eles\n> são **omitidos** do `eventData` quando não há dispositivo ou veículo associado. O\n> envelope interno ainda carrega `deviceId` como string vazia — é uma restrição do\n> nosso armazenamento, não um identificador válido. Use o `eventData`.\n\n> **Trate o webhook como sinal, não como fonte da verdade.** O evento é publicado\n> dentro da transação do domínio, então numa falha rara você pode receber um evento\n> cujo estado não persistiu. Em caso de divergência, reconcilie por\n> `GET /public/v2/routes`.\n\n> **`eventData` é aninhado.** Um handler que espera o formato plano dos demais tipos\n> não encontra nenhum campo — eles vivem em `eventData.route`.\n\n---\n\nEntregue pela assinatura do tipo **`routes`**.\nA Cobli envia este evento como `POST application/json` para a URL cadastrada na\nassinatura, assinado em `X-Cobli-Signature`. Responda `2xx` em até 5 segundos e\ndeduplique por `eventId`.\n",
        "security": [
          {
            "CobliWebhookSignature": []
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Envelope do evento `route_started`.",
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/EventEnvelope"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "eventType": {
                        "type": "string",
                        "enum": [
                          "route_started"
                        ]
                      },
                      "eventData": {
                        "allOf": [
                          {
                            "$ref": "#/components/schemas/RouteActivityEventData"
                          },
                          {
                            "type": "object",
                            "required": [
                              "route"
                            ]
                          }
                        ]
                      }
                    }
                  }
                ]
              },
              "example": {
                "eventId": "b1c2d3e4-0000-0000-0000-999900001111",
                "eventTime": "2026-09-03T08:12:00Z",
                "eventType": "route_started",
                "eventData": {
                  "deviceId": "865648066819319",
                  "vehicleId": "55555555-5555-5555-5555-555555555555",
                  "fleetId": "11111111-1111-1111-1111-111111111111",
                  "licensePlate": "ABC1D23",
                  "route": {
                    "routeId": "22222222-2222-2222-2222-222222222222",
                    "externalId": "ERP-ROUTE-1",
                    "name": "Rota 1",
                    "driverId": "44444444-4444-4444-4444-444444444444",
                    "driverName": "Nome do Motorista",
                    "plannedStartTime": "2026-09-03T08:00:00Z",
                    "plannedEndTime": "2026-09-03T17:00:00Z",
                    "plannedDurationInMillis": 32400000,
                    "plannedDistanceInMeters": 12000,
                    "status": "IN_PROGRESS",
                    "executedStartTime": "2026-09-03T08:12:00Z"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/WebhookAck"
          },
          "400": {
            "$ref": "#/components/responses/WebhookRejected"
          },
          "429": {
            "$ref": "#/components/responses/WebhookThrottled"
          },
          "500": {
            "$ref": "#/components/responses/WebhookServerError"
          }
        }
      }
    },
    "route_finished": {
      "post": {
        "tags": [
          "Eventos de Webhook"
        ],
        "operationId": "webhookRouteFinished",
        "summary": "route_finished — Rota encerrada",
        "description": "Disparado quando a rota é **encerrada**, qualquer que seja o desfecho.\n\nO resultado está em `route.outcome`:\n\n| `outcome` | Significado |\n|-----------|-------------|\n| `EXECUTED` | Rota cumprida integralmente |\n| `PARTIALLY_EXECUTED` | Rota cumprida em parte |\n| `UNEXECUTED` | Rota não executada |\n| `EXPIRED` | **A Cobli** encerrou a rota por inatividade — não foi o motorista que a fechou |\n\n> `EXPIRED` é a única forma de distinguir um encerramento automático de um\n> encerramento pelo motorista: nenhum outro campo carrega essa informação.\n\n> **`deviceId` e `vehicleId` podem não vir.** Uma rota encerrada por inatividade sem\n> nunca ter iniciado pode não ter dispositivo nem veículo associados; nesse caso os\n> campos são **omitidos** do `eventData`. O envelope interno ainda carrega `deviceId`\n> como string vazia — é uma restrição do nosso armazenamento, não um identificador\n> válido. Use o `eventData`.\n\n> **Trate o webhook como sinal, não como fonte da verdade.** O evento é publicado\n> dentro da transação do domínio, então numa falha rara você pode receber um evento\n> cujo estado não persistiu. Em caso de divergência, reconcilie por\n> `GET /public/v2/routes`.\n\n> **`eventData` é aninhado.** Um handler que espera o formato plano dos demais tipos\n> não encontra nenhum campo — eles vivem em `eventData.route`.\n\n---\n\nEntregue pela assinatura do tipo **`routes`**.\nA Cobli envia este evento como `POST application/json` para a URL cadastrada na\nassinatura, assinado em `X-Cobli-Signature`. Responda `2xx` em até 5 segundos e\ndeduplique por `eventId`.\n",
        "security": [
          {
            "CobliWebhookSignature": []
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Envelope do evento `route_finished`.",
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/EventEnvelope"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "eventType": {
                        "type": "string",
                        "enum": [
                          "route_finished"
                        ]
                      },
                      "eventData": {
                        "allOf": [
                          {
                            "$ref": "#/components/schemas/RouteActivityEventData"
                          },
                          {
                            "type": "object",
                            "required": [
                              "route"
                            ]
                          }
                        ]
                      }
                    }
                  }
                ]
              },
              "example": {
                "eventId": "c2d3e4f5-0000-0000-0000-999900002222",
                "eventTime": "2026-09-03T17:20:00Z",
                "eventType": "route_finished",
                "eventData": {
                  "deviceId": "865648066819319",
                  "vehicleId": "55555555-5555-5555-5555-555555555555",
                  "fleetId": "11111111-1111-1111-1111-111111111111",
                  "licensePlate": "ABC1D23",
                  "route": {
                    "routeId": "22222222-2222-2222-2222-222222222222",
                    "externalId": "ERP-ROUTE-1",
                    "name": "Rota 1",
                    "driverId": "44444444-4444-4444-4444-444444444444",
                    "driverName": "Nome do Motorista",
                    "plannedStartTime": "2026-09-03T08:00:00Z",
                    "plannedEndTime": "2026-09-03T17:00:00Z",
                    "plannedDurationInMillis": 32400000,
                    "plannedDistanceInMeters": 12000,
                    "status": "FINISHED",
                    "outcome": "EXECUTED",
                    "executedStartTime": "2026-09-03T08:12:00Z",
                    "executedEndTime": "2026-09-03T17:20:00Z",
                    "executedDurationInMillis": 32880000,
                    "executedDistanceInMeters": 12500
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/WebhookAck"
          },
          "400": {
            "$ref": "#/components/responses/WebhookRejected"
          },
          "429": {
            "$ref": "#/components/responses/WebhookThrottled"
          },
          "500": {
            "$ref": "#/components/responses/WebhookServerError"
          }
        }
      }
    },
    "activity_completed": {
      "post": {
        "tags": [
          "Eventos de Webhook"
        ],
        "operationId": "webhookActivityCompleted",
        "summary": "activity_completed — Parada concluída",
        "description": "Disparado quando uma parada é **concluída**, total ou parcialmente.\n\n`activity.outcome` distingue os dois casos — e `PARTIALLY_COMPLETED` **é conclusão,\nnão falha**: falha é o tipo `activity_failed`, que pode ser assinado à parte.\n\n`activity.windowCompliance` entrega o cumprimento da janela já resolvido contra\n`activity.timeWindows`: `ON_TIME` quando a conclusão cai dentro de **qualquer** janela,\n`EARLY` só quando precede todas, `LATE` no resto — inclusive no vão entre duas janelas.\n\n> **Assine o grupo `activities`** — plural, literalmente `\"activities\"` em `event_types`.\n> Grupo de composição fechada: entrega exatamente `activity_completed` e\n> `activity_failed`.\n\n> O bloco `route` está presente, salvo numa parada que não pertence a nenhuma rota.\n\n> **`deviceId` e `vehicleId` podem não vir.** O contrato os declara opcionais e eles\n> são **omitidos** do `eventData` quando não há dispositivo ou veículo associado. O\n> envelope interno ainda carrega `deviceId` como string vazia — é uma restrição do\n> nosso armazenamento, não um identificador válido. Use o `eventData`.\n\n> **Trate o webhook como sinal, não como fonte da verdade.** O evento é publicado\n> dentro da transação do domínio, então numa falha rara você pode receber um evento\n> cujo estado não persistiu. Em caso de divergência, reconcilie por\n> `GET /public/v2/routes`.\n\n> **`eventData` é aninhado.** Um handler que espera o formato plano dos demais tipos\n> não encontra nenhum campo — eles vivem em `eventData.route` e `eventData.activity`.\n\n---\n\nEntregue pela assinatura do tipo **`activities`**.\nA Cobli envia este evento como `POST application/json` para a URL cadastrada na\nassinatura, assinado em `X-Cobli-Signature`. Responda `2xx` em até 5 segundos e\ndeduplique por `eventId`.\n",
        "security": [
          {
            "CobliWebhookSignature": []
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Envelope do evento `activity_completed`.",
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/EventEnvelope"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "eventType": {
                        "type": "string",
                        "enum": [
                          "activity_completed"
                        ]
                      },
                      "eventData": {
                        "allOf": [
                          {
                            "$ref": "#/components/schemas/RouteActivityEventData"
                          },
                          {
                            "type": "object",
                            "required": [
                              "activity"
                            ]
                          }
                        ]
                      }
                    }
                  }
                ]
              },
              "example": {
                "eventId": "a8b9c0d1-0000-0000-0000-888899990000",
                "eventTime": "2026-09-03T12:00:00Z",
                "eventType": "activity_completed",
                "eventData": {
                  "deviceId": "865648066819319",
                  "vehicleId": "55555555-5555-5555-5555-555555555555",
                  "fleetId": "11111111-1111-1111-1111-111111111111",
                  "licensePlate": "ABC1D23",
                  "route": {
                    "routeId": "22222222-2222-2222-2222-222222222222",
                    "externalId": "ERP-ROUTE-1",
                    "name": "Rota 1",
                    "driverId": "44444444-4444-4444-4444-444444444444",
                    "driverName": "Nome do Motorista",
                    "plannedStartTime": "2026-09-03T08:00:00Z",
                    "plannedEndTime": "2026-09-03T17:00:00Z",
                    "plannedDurationInMillis": 32400000,
                    "plannedDistanceInMeters": 12000,
                    "status": "IN_PROGRESS",
                    "executedStartTime": "2026-09-03T08:12:00Z"
                  },
                  "activity": {
                    "activityId": "33333333-3333-3333-3333-333333333333",
                    "externalId": "ERP-ORDER-1",
                    "name": "Parada 1",
                    "position": 2,
                    "driverId": "44444444-4444-4444-4444-444444444444",
                    "driverName": "Nome do Motorista",
                    "plannedArrivalTime": "2026-09-03T11:30:00Z",
                    "plannedEndTime": "2026-09-03T11:45:00Z",
                    "arrivalTime": "2026-09-03T11:52:00Z",
                    "plannedDurationInMillis": 900000,
                    "destination": {
                      "latitude": -23.5629,
                      "longitude": -46.6544,
                      "country": "BR",
                      "state": "SP",
                      "city": "Sao Paulo",
                      "neighborhood": "Bela Vista",
                      "streetAddress": "Avenida Paulista",
                      "streetNumber": "1000",
                      "streetComplement": "Conjunto 42",
                      "postalCode": "01310-100"
                    },
                    "timeWindows": [
                      {
                        "earliest": "2026-09-03T11:00:00Z",
                        "latest": "2026-09-03T13:00:00Z"
                      }
                    ],
                    "outcome": "COMPLETED",
                    "completedAt": "2026-09-03T12:00:00Z",
                    "observation": "entregue ao porteiro",
                    "windowCompliance": "ON_TIME",
                    "executedEndTime": "2026-09-03T12:00:00Z",
                    "executedDurationInMillis": 480000
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/WebhookAck"
          },
          "400": {
            "$ref": "#/components/responses/WebhookRejected"
          },
          "429": {
            "$ref": "#/components/responses/WebhookThrottled"
          },
          "500": {
            "$ref": "#/components/responses/WebhookServerError"
          }
        }
      }
    },
    "activity_failed": {
      "post": {
        "tags": [
          "Eventos de Webhook"
        ],
        "operationId": "webhookActivityFailed",
        "summary": "activity_failed — Parada marcada como não realizada",
        "description": "Disparado quando uma parada é marcada como **não realizada**.\n\n`activity.outcome` e `activity.windowCompliance` **não aparecem** neste tipo — o\npróprio `eventType` já é o desfecho.\n\n> `activity.completedAt` aqui é o instante da **tentativa**, não de uma conclusão, e\n> `activity.driverId` é quem **tentou** atender a parada.\n\n> O bloco `route` está presente, salvo numa parada que não pertence a nenhuma rota.\n\n> **`deviceId` e `vehicleId` podem não vir.** O contrato os declara opcionais e eles\n> são **omitidos** do `eventData` quando não há dispositivo ou veículo associado. O\n> envelope interno ainda carrega `deviceId` como string vazia — é uma restrição do\n> nosso armazenamento, não um identificador válido. Use o `eventData`.\n\n> **Trate o webhook como sinal, não como fonte da verdade.** O evento é publicado\n> dentro da transação do domínio, então numa falha rara você pode receber um evento\n> cujo estado não persistiu. Em caso de divergência, reconcilie por\n> `GET /public/v2/routes`.\n\n> **`eventData` é aninhado.** Um handler que espera o formato plano dos demais tipos\n> não encontra nenhum campo — eles vivem em `eventData.route` e `eventData.activity`.\n\n---\n\nEntregue pela assinatura do tipo **`activities`**.\nA Cobli envia este evento como `POST application/json` para a URL cadastrada na\nassinatura, assinado em `X-Cobli-Signature`. Responda `2xx` em até 5 segundos e\ndeduplique por `eventId`.\n",
        "security": [
          {
            "CobliWebhookSignature": []
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Envelope do evento `activity_failed`.",
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/EventEnvelope"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "eventType": {
                        "type": "string",
                        "enum": [
                          "activity_failed"
                        ]
                      },
                      "eventData": {
                        "allOf": [
                          {
                            "$ref": "#/components/schemas/RouteActivityEventData"
                          },
                          {
                            "type": "object",
                            "required": [
                              "activity"
                            ]
                          }
                        ]
                      }
                    }
                  }
                ]
              },
              "example": {
                "eventId": "d3e4f5a6-0000-0000-0000-999900003333",
                "eventTime": "2026-09-03T12:00:00Z",
                "eventType": "activity_failed",
                "eventData": {
                  "deviceId": "865648066819319",
                  "vehicleId": "55555555-5555-5555-5555-555555555555",
                  "fleetId": "11111111-1111-1111-1111-111111111111",
                  "licensePlate": "ABC1D23",
                  "route": {
                    "routeId": "22222222-2222-2222-2222-222222222222",
                    "externalId": "ERP-ROUTE-1",
                    "name": "Rota 1",
                    "driverId": "44444444-4444-4444-4444-444444444444",
                    "driverName": "Nome do Motorista",
                    "plannedStartTime": "2026-09-03T08:00:00Z",
                    "plannedEndTime": "2026-09-03T17:00:00Z",
                    "plannedDurationInMillis": 32400000,
                    "plannedDistanceInMeters": 12000,
                    "status": "IN_PROGRESS",
                    "executedStartTime": "2026-09-03T08:12:00Z"
                  },
                  "activity": {
                    "activityId": "33333333-3333-3333-3333-333333333333",
                    "externalId": "ERP-ORDER-1",
                    "name": "Parada 1",
                    "position": 2,
                    "driverId": "44444444-4444-4444-4444-444444444444",
                    "driverName": "Nome do Motorista",
                    "plannedArrivalTime": "2026-09-03T11:30:00Z",
                    "plannedEndTime": "2026-09-03T11:45:00Z",
                    "arrivalTime": "2026-09-03T11:52:00Z",
                    "plannedDurationInMillis": 900000,
                    "destination": {
                      "latitude": -23.5629,
                      "longitude": -46.6544,
                      "country": "BR",
                      "state": "SP",
                      "city": "Sao Paulo",
                      "neighborhood": "Bela Vista",
                      "streetAddress": "Avenida Paulista",
                      "streetNumber": "1000",
                      "streetComplement": "Conjunto 42",
                      "postalCode": "01310-100"
                    },
                    "timeWindows": [
                      {
                        "earliest": "2026-09-03T11:00:00Z",
                        "latest": "2026-09-03T13:00:00Z"
                      }
                    ],
                    "completedAt": "2026-09-03T12:00:00Z",
                    "observation": "estabelecimento fechado",
                    "executedEndTime": "2026-09-03T12:00:00Z",
                    "executedDurationInMillis": 480000
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/WebhookAck"
          },
          "400": {
            "$ref": "#/components/responses/WebhookRejected"
          },
          "429": {
            "$ref": "#/components/responses/WebhookThrottled"
          },
          "500": {
            "$ref": "#/components/responses/WebhookServerError"
          }
        }
      }
    },
    "ignition_lock_status_changed": {
      "post": {
        "tags": [
          "Eventos de Webhook"
        ],
        "operationId": "webhookIgnitionLockStatusChanged",
        "summary": "ignition_lock_status_changed — Status da trava de ignição mudou",
        "description": "Disparado quando o **status global** da trava de ignição do veículo muda.\n\nO `status` é derivado da combinação entre o valor desejado (configurado no app) e o\nvalor reportado pelo dispositivo, e esconde essa distinção de você:\n\n| `status` | Significado |\n|----------|-------------|\n| `inactive` | Trava desligada — o dispositivo reportou a trava desativada e nada está pendente |\n| `pending` | Mudança em propagação — o app pediu uma configuração que o dispositivo ainda não confirmou (ou vice-versa) |\n| `active` | Trava ligada — o dispositivo confirmou que a trava está ativa |\n\n> **Disponibilidade.** Apenas para frotas com hardware compatível. Frotas sem trava de\n> ignição instalada não recebem este evento.\n\n> **Campos posicionais vêm como `null`, não ausentes.** Este evento descreve o estado\n> de uma configuração, não uma telemetria: `latitude`, `longitude`, `heading`,\n> `odometer`, `driverId`, `cobliId` e os demais campos de telemetria **estão presentes\n> no JSON com valor `null`**. `speedInKmh` não aparece. `licensePlate` é incluído\n> quando o veículo tem placa cadastrada e omitido caso contrário. `networkSignal`\n> nunca aparece neste evento.\n\n---\n\nAssine o tipo **`ignition_lock_status_changed`** para receber este evento.\nA Cobli envia este evento como `POST application/json` para a URL cadastrada na\nassinatura, assinado em `X-Cobli-Signature`. Responda `2xx` em até 5 segundos e\ndeduplique por `eventId`.\n",
        "security": [
          {
            "CobliWebhookSignature": []
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Envelope do evento `ignition_lock_status_changed`.",
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/EventEnvelope"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "eventType": {
                        "type": "string",
                        "enum": [
                          "ignition_lock_status_changed"
                        ]
                      },
                      "eventData": {
                        "$ref": "#/components/schemas/IgnitionLockStatusChangedEventData"
                      }
                    }
                  }
                ]
              },
              "example": {
                "eventId": "8d2d2f73-7842-3bf1-9d3a-a7c4c6e7f4d2",
                "eventTime": "2026-05-31T22:00:00Z",
                "eventType": "ignition_lock_status_changed",
                "eventData": {
                  "deviceId": "879797465464874",
                  "vehicleId": "05009b4a-bed3-4431-955a-4c3e80dc6697",
                  "fleetId": "cf3f1990-2ce3-4ed9-85c5-9a528295ecfe",
                  "licensePlate": "ABC1D23",
                  "status": "active",
                  "cobliId": null,
                  "driverId": null,
                  "latitude": null,
                  "longitude": null,
                  "heading": null,
                  "numberOfSatellites": null,
                  "hdop": null,
                  "ignition": null,
                  "odometer": null,
                  "batteryVoltage": null,
                  "connectionType": null,
                  "rpm": null,
                  "fuelLevel": null
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/WebhookAck"
          },
          "400": {
            "$ref": "#/components/responses/WebhookRejected"
          },
          "429": {
            "$ref": "#/components/responses/WebhookThrottled"
          },
          "500": {
            "$ref": "#/components/responses/WebhookServerError"
          }
        }
      }
    },
    "allow_list_changed": {
      "post": {
        "tags": [
          "Eventos de Webhook"
        ],
        "operationId": "webhookAllowListChanged",
        "summary": "allow_list_changed — Lista de motoristas autorizados mudou",
        "description": "Disparado quando a **lista de motoristas autorizados** a operar o veículo muda — seja\nporque um motorista foi adicionado ou removido da configuração, seja porque o `status`\nglobal mudou (por exemplo, o dispositivo confirmou a propagação).\n\n| `status` | Significado |\n|----------|-------------|\n| `inactive` | Nenhum identificador autorizado configurado no dispositivo |\n| `pending` | Mudança em propagação — o app pediu uma adição/remoção que o dispositivo ainda não confirmou |\n| `active` | Pelo menos um identificador autorizado confirmado no dispositivo |\n\n> O `status` é derivado dos **identificadores** autorizados (chaveiro iButton, cartão\n> RFID), não dos motoristas. Um identificador autorizado sem motorista associado já leva\n> o status a `active` — nesse caso você recebe `active` com `drivers_added` vazio.\n\n### Sobre `drivers_added` e `drivers_removed`\n\n- **Atenção ao `snake_case`.** São os únicos campos do payload fora do padrão\n  `camelCase`. Leia exatamente `drivers_added` e `drivers_removed`.\n- São a **diferença incremental** desde o último evento enviado ao seu endpoint — não a\n  lista completa de autorizados.\n- Identificadores físicos sem motorista associado no momento do evento **não aparecem**\n  em nenhuma das duas listas.\n- Ambos podem vir vazios quando o evento foi disparado puramente por uma transição de\n  `status` (por exemplo, `pending` → `active`).\n\n> **Disponibilidade.** Apenas para frotas com hardware compatível.\n\n> **Campos posicionais vêm como `null`.** Como em `ignition_lock_status_changed`, os\n> campos de telemetria estão presentes no JSON com valor `null`. Em especial,\n> `driverId` é **sempre** `null` aqui: os motoristas vêm em `drivers_added` e\n> `drivers_removed`, nunca em `driverId`.\n\n---\n\nAssine o tipo **`allow_list_changed`** para receber este evento.\nA Cobli envia este evento como `POST application/json` para a URL cadastrada na\nassinatura, assinado em `X-Cobli-Signature`. Responda `2xx` em até 5 segundos e\ndeduplique por `eventId`.\n",
        "security": [
          {
            "CobliWebhookSignature": []
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Envelope do evento `allow_list_changed`.",
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/EventEnvelope"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "eventType": {
                        "type": "string",
                        "enum": [
                          "allow_list_changed"
                        ]
                      },
                      "eventData": {
                        "$ref": "#/components/schemas/AllowListChangedEventData"
                      }
                    }
                  }
                ]
              },
              "example": {
                "eventId": "1f3a8b9c-4d2e-3f00-9876-aabbccddeeff",
                "eventTime": "2026-05-31T22:00:00Z",
                "eventType": "allow_list_changed",
                "eventData": {
                  "deviceId": "879797465464874",
                  "vehicleId": "05009b4a-bed3-4431-955a-4c3e80dc6697",
                  "fleetId": "cf3f1990-2ce3-4ed9-85c5-9a528295ecfe",
                  "licensePlate": "ABC1D23",
                  "status": "pending",
                  "drivers_added": [
                    "d1234567-0000-0000-0000-000000000001"
                  ],
                  "drivers_removed": [
                    "d7654321-0000-0000-0000-000000000002"
                  ],
                  "cobliId": null,
                  "driverId": null,
                  "latitude": null,
                  "longitude": null,
                  "heading": null,
                  "numberOfSatellites": null,
                  "hdop": null,
                  "ignition": null,
                  "odometer": null,
                  "batteryVoltage": null,
                  "connectionType": null,
                  "rpm": null,
                  "fuelLevel": null
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/WebhookAck"
          },
          "400": {
            "$ref": "#/components/responses/WebhookRejected"
          },
          "429": {
            "$ref": "#/components/responses/WebhookThrottled"
          },
          "500": {
            "$ref": "#/components/responses/WebhookServerError"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "CobliWebhookSignature": {
        "name": "X-Cobli-Signature",
        "type": "apiKey",
        "in": "header",
        "description": "Autenticação dos eventos que a **Cobli envia para o seu endpoint** — não se aplica às chamadas que você faz para a API da Cobli.\n\nToda entrega traz o header `X-Cobli-Signature` com o HMAC-SHA256 do **corpo bruto** da requisição, codificado em hexadecimal minúsculo e calculado com a `secretKey` cadastrada na assinatura.\n\nValide **antes** de desserializar o payload e rejeite com `400` quando a assinatura for inválida ou ausente. Compare em tempo constante (`hmac.compare_digest`, `crypto.timingSafeEqual`) — comparação de string comum vaza tempo. O conteúdo assinado é a sequência de bytes UTF-8 exatamente como recebida: não reserialize nem normalize o JSON antes de calcular o HMAC.\n\n```python import hmac, hashlib\ndef verificar(secret: str, body: bytes, assinatura: str) -> bool:\n    esperado = hmac.new(secret.encode(), body, hashlib.sha256).hexdigest()\n    return hmac.compare_digest(esperado, assinatura)\n```\n\nAssinaturas com **Bearer auth** habilitado recebem também um header `Authorization: Bearer <token>`; o HMAC continua valendo."
      },
      "APIKey": {
        "name": "cobli-api-key",
        "description": "O método de autenticação suportado pela API da Cobli é a API Key. Você deve gerá-la no painel da Cobli. Para isso, você deve acessar a guia de `Integrações` dentro do Painel, depois a guia de `Chaves de API` e por fim, clicar no botão `Nova chave de API`. Depois de gerada a chave, deve ser utilizada no cabeçalho como `cobli-api-key`. No caso de dúvidas, acesse o link direto: https://painel.cobli.co/apis",
        "type": "apiKey",
        "in": "header"
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "message": {
            "description": "Mensagem que descreve o erro ocorrido.",
            "type": "string"
          }
        }
      },
      "RouteActivityEventData": {
        "type": "object",
        "title": "eventData de rota e parada",
        "description": "Único `eventData` **aninhado** do catálogo: os dados da rota vão em `route` e os da parada em `activity`. Um handler que espera o formato plano não encontra nenhum campo.\n\n`deviceId`, `vehicleId` e `licensePlate` são **opcionais** aqui — uma rota encerrada por inatividade sem nunca ter iniciado pode não ter dispositivo nem veículo associados. Os dois blocos também podem estar ausentes.",
        "properties": {
          "deviceId": {
            "type": "string",
            "description": "Identificador do dispositivo. Omitido quando a rota não tem dispositivo associado.",
            "example": "865648066819319"
          },
          "vehicleId": {
            "type": "string",
            "format": "uuid",
            "description": "Identificador do veículo. Omitido quando a rota não tem veículo associado.",
            "example": "55555555-5555-5555-5555-555555555555"
          },
          "fleetId": {
            "type": "string",
            "format": "uuid",
            "description": "Identificador da frota.",
            "example": "11111111-1111-1111-1111-111111111111"
          },
          "licensePlate": {
            "type": "string",
            "description": "Placa do veículo, quando há veículo associado.",
            "example": "ABC1D23"
          },
          "route": {
            "type": "object",
            "title": "route",
            "description": "Dados da rota. Presente nos quatro tipos, exceto numa parada que não pertence a nenhuma rota.",
            "required": [
              "routeId"
            ],
            "properties": {
              "routeId": {
                "type": "string",
                "format": "uuid",
                "description": "Identificador da rota na Cobli.",
                "example": "22222222-2222-2222-2222-222222222222"
              },
              "externalId": {
                "type": "string",
                "description": "O vínculo com o seu sistema: o identificador que você enviou ao criar a rota.",
                "example": "ERP-ROUTE-1"
              },
              "name": {
                "type": "string",
                "description": "Nome da rota.",
                "example": "Rota 1"
              },
              "status": {
                "type": "string",
                "description": "Situação da rota no momento do evento.",
                "example": "IN_PROGRESS"
              },
              "outcome": {
                "type": "string",
                "enum": [
                  "EXECUTED",
                  "PARTIALLY_EXECUTED",
                  "UNEXECUTED",
                  "EXPIRED"
                ],
                "description": "Resultado da rota, presente apenas em `route_finished`. `EXPIRED` significa que **a Cobli** encerrou a rota por inatividade, e não que o motorista a fechou — distinção que nenhum outro campo carrega.",
                "example": "EXECUTED"
              },
              "driverId": {
                "type": "string",
                "format": "uuid",
                "description": "Motorista responsável pela rota.",
                "example": "44444444-4444-4444-4444-444444444444"
              },
              "driverName": {
                "type": "string",
                "description": "Nome resolvido a partir de `driverId` no momento do evento. **Omitido** quando o motorista não é encontrado no cadastro — trate `driverId` como a identidade e o nome como conveniência de exibição.",
                "example": "Nome do Motorista"
              },
              "plannedStartTime": {
                "type": "string",
                "format": "date-time",
                "description": "Início planejado da rota.",
                "example": "2026-09-03T08:00:00Z"
              },
              "plannedEndTime": {
                "type": "string",
                "format": "date-time",
                "description": "Fim planejado da rota.",
                "example": "2026-09-03T17:00:00Z"
              },
              "executedStartTime": {
                "type": "string",
                "format": "date-time",
                "description": "Início efetivo da rota.",
                "example": "2026-09-03T08:12:00Z"
              },
              "executedEndTime": {
                "type": "string",
                "format": "date-time",
                "description": "Fim efetivo da rota.",
                "example": "2026-09-03T17:20:00Z"
              },
              "plannedDurationInMillis": {
                "type": "integer",
                "format": "int64",
                "description": "Duração planejada da rota, em milissegundos.",
                "example": 32400000
              },
              "executedDurationInMillis": {
                "type": "integer",
                "format": "int64",
                "description": "Duração efetiva da rota, em milissegundos.",
                "example": 32880000
              },
              "plannedDistanceInMeters": {
                "type": "integer",
                "description": "Distância planejada da rota, em metros.",
                "example": 12000
              },
              "executedDistanceInMeters": {
                "type": "integer",
                "description": "Distância percorrida na rota, em metros.",
                "example": 12500
              }
            }
          },
          "activity": {
            "type": "object",
            "title": "activity",
            "description": "Dados da parada. Presente apenas em `activity_completed` e `activity_failed`.",
            "required": [
              "activityId"
            ],
            "properties": {
              "activityId": {
                "type": "string",
                "format": "uuid",
                "description": "Identificador da parada na Cobli.",
                "example": "33333333-3333-3333-3333-333333333333"
              },
              "externalId": {
                "type": "string",
                "description": "O vínculo com o seu sistema: o identificador que você enviou ao criar o pedido.",
                "example": "ERP-ORDER-1"
              },
              "name": {
                "type": "string",
                "description": "Nome da parada.",
                "example": "Parada 1"
              },
              "position": {
                "type": "integer",
                "description": "Posição da parada na sequência da rota.",
                "example": 2
              },
              "outcome": {
                "type": "string",
                "enum": [
                  "COMPLETED",
                  "PARTIALLY_COMPLETED"
                ],
                "description": "Resultado da parada, presente apenas em `activity_completed`. `PARTIALLY_COMPLETED` é conclusão, não falha — falha é o tipo `activity_failed`.",
                "example": "COMPLETED"
              },
              "driverId": {
                "type": "string",
                "format": "uuid",
                "description": "Quem **atendeu** a parada, registrado na comprovação — em `activity_failed`, quem **tentou**. Pode diferir de `route.driverId` quando a rota foi reatribuída depois da parada servida, e é o único motorista do evento quando a parada não tem rota. **Ausente** quando a origem não registrou o motorista: não há fallback para `route.driverId`.",
                "example": "44444444-4444-4444-4444-444444444444"
              },
              "driverName": {
                "type": "string",
                "description": "Nome resolvido a partir do `driverId` da parada. Omitido quando o motorista não é encontrado no cadastro.",
                "example": "Nome do Motorista"
              },
              "completedAt": {
                "type": "string",
                "format": "date-time",
                "description": "Momento da conclusão. Em `activity_failed` é o instante da **tentativa**, não de uma conclusão.",
                "example": "2026-09-03T12:00:00Z"
              },
              "observation": {
                "type": "string",
                "description": "Observação registrada pelo motorista na comprovação.",
                "example": "entregue ao porteiro"
              },
              "windowCompliance": {
                "type": "string",
                "enum": [
                  "EARLY",
                  "ON_TIME",
                  "LATE"
                ],
                "description": "Cumprimento da janela já resolvido contra `timeWindows`, presente apenas em `activity_completed`: `ON_TIME` quando a conclusão cai dentro de **qualquer** janela, `EARLY` só quando precede todas, `LATE` no resto — inclusive no vão entre duas janelas.",
                "example": "ON_TIME"
              },
              "plannedArrivalTime": {
                "type": "string",
                "format": "date-time",
                "description": "Chegada planejada na parada.",
                "example": "2026-09-03T11:30:00Z"
              },
              "plannedEndTime": {
                "type": "string",
                "format": "date-time",
                "description": "Fim planejado do atendimento.",
                "example": "2026-09-03T11:45:00Z"
              },
              "arrivalTime": {
                "type": "string",
                "format": "date-time",
                "description": "Chegada efetiva na parada.",
                "example": "2026-09-03T11:52:00Z"
              },
              "executedEndTime": {
                "type": "string",
                "format": "date-time",
                "description": "Fim efetivo do atendimento.",
                "example": "2026-09-03T12:00:00Z"
              },
              "plannedDurationInMillis": {
                "type": "integer",
                "format": "int64",
                "description": "Duração planejada do atendimento, em milissegundos.",
                "example": 900000
              },
              "executedDurationInMillis": {
                "type": "integer",
                "format": "int64",
                "description": "Duração efetiva do atendimento, em milissegundos.",
                "example": 480000
              },
              "destination": {
                "type": "object",
                "title": "destination",
                "description": "Endereço de destino da parada.",
                "properties": {
                  "latitude": {
                    "type": "number",
                    "format": "double",
                    "example": -23.5629
                  },
                  "longitude": {
                    "type": "number",
                    "format": "double",
                    "example": -46.6544
                  },
                  "country": {
                    "type": "string",
                    "example": "BR"
                  },
                  "state": {
                    "type": "string",
                    "example": "SP"
                  },
                  "city": {
                    "type": "string",
                    "example": "Sao Paulo"
                  },
                  "neighborhood": {
                    "type": "string",
                    "example": "Bela Vista"
                  },
                  "streetAddress": {
                    "type": "string",
                    "example": "Avenida Paulista"
                  },
                  "streetNumber": {
                    "type": "string",
                    "example": "1000"
                  },
                  "streetComplement": {
                    "type": "string",
                    "example": "Conjunto 42"
                  },
                  "postalCode": {
                    "type": "string",
                    "example": "01310-100"
                  }
                }
              },
              "timeWindows": {
                "type": "array",
                "description": "Janelas de atendimento acordadas para a parada. `windowCompliance` já traz o veredito resolvido contra elas.",
                "items": {
                  "type": "object",
                  "title": "timeWindow",
                  "required": [
                    "earliest",
                    "latest"
                  ],
                  "properties": {
                    "earliest": {
                      "type": "string",
                      "format": "date-time",
                      "example": "2026-09-03T11:00:00Z"
                    },
                    "latest": {
                      "type": "string",
                      "format": "date-time",
                      "example": "2026-09-03T13:00:00Z"
                    }
                  }
                }
              }
            }
          }
        }
      },
      "ConfigStateEventData": {
        "type": "object",
        "title": "eventData de estado de configuração",
        "description": "Base dos eventos que descrevem o estado de uma configuração do veículo, e não uma telemetria.\n\n**Os campos posicionais vêm como `null`, não ausentes.** Diferente de todos os outros tipos, aqui `latitude`, `longitude`, `heading`, `odometer`, `driverId`, `cobliId`, `ignition`, `batteryVoltage`, `connectionType`, `rpm`, `fuelLevel`, `numberOfSatellites` e `hdop` **estão presentes no JSON com valor `null`**. Trate-os como sempre nulos para estes tipos. `speedInKmh` não aparece.",
        "required": [
          "deviceId",
          "vehicleId"
        ],
        "properties": {
          "deviceId": {
            "type": "string",
            "description": "Identificador do dispositivo.",
            "example": "879797465464874"
          },
          "vehicleId": {
            "type": "string",
            "format": "uuid",
            "description": "Identificador do veículo.",
            "example": "05009b4a-bed3-4431-955a-4c3e80dc6697"
          },
          "fleetId": {
            "type": "string",
            "format": "uuid",
            "description": "Identificador da frota.",
            "example": "cf3f1990-2ce3-4ed9-85c5-9a528295ecfe"
          },
          "licensePlate": {
            "type": "string",
            "description": "Placa do veículo. Incluída quando o veículo tem placa cadastrada e omitida caso contrário.",
            "example": "ABC1D23"
          },
          "cobliId": {
            "type": [
              "string",
              "null"
            ],
            "description": "Sempre `null` neste tipo de evento."
          },
          "driverId": {
            "type": [
              "string",
              "null"
            ],
            "description": "Sempre `null` neste tipo de evento."
          },
          "latitude": {
            "type": [
              "number",
              "null"
            ],
            "description": "Sempre `null` neste tipo de evento."
          },
          "longitude": {
            "type": [
              "number",
              "null"
            ],
            "description": "Sempre `null` neste tipo de evento."
          },
          "heading": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Sempre `null` neste tipo de evento."
          },
          "numberOfSatellites": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Sempre `null` neste tipo de evento."
          },
          "hdop": {
            "type": [
              "number",
              "null"
            ],
            "description": "Sempre `null` neste tipo de evento."
          },
          "ignition": {
            "type": [
              "string",
              "null"
            ],
            "description": "Sempre `null` neste tipo de evento."
          },
          "odometer": {
            "type": [
              "number",
              "null"
            ],
            "description": "Sempre `null` neste tipo de evento."
          },
          "batteryVoltage": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Sempre `null` neste tipo de evento."
          },
          "connectionType": {
            "type": [
              "string",
              "null"
            ],
            "description": "Sempre `null` neste tipo de evento."
          },
          "rpm": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Sempre `null` neste tipo de evento."
          },
          "fuelLevel": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Sempre `null` neste tipo de evento."
          },
          "networkSignal": {
            "type": "integer",
            "description": "Intensidade do sinal da rede celular no **índice CSQ** do 3GPP TS 27.007 §8.5 (0 a 31, maiores são mais fortes; `99` = desconhecido). Neste evento é **sempre omitido**: ele descreve estado de configuração, não telemetria.",
            "example": 22
          }
        }
      },
      "IgnitionLockStatusChangedEventData": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ConfigStateEventData"
          },
          {
            "type": "object",
            "title": "eventData de trava de ignição",
            "required": [
              "status"
            ],
            "properties": {
              "status": {
                "type": "string",
                "enum": [
                  "inactive",
                  "pending",
                  "active"
                ],
                "description": "Status **global** da trava, já resolvido a partir do valor desejado (configurado no app) e do valor reportado pelo dispositivo:\n\n- `inactive` — trava desligada: o dispositivo reportou que a trava está\n  desativada e nenhuma mudança está pendente.\n\n- `pending` — mudança em propagação: o app pediu uma configuração que o\n  dispositivo ainda não confirmou (ou vice-versa).\n\n- `active` — trava ligada: o dispositivo confirmou que a trava está\n  ativa.",
                "example": "active"
              }
            }
          }
        ]
      },
      "AllowListChangedEventData": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ConfigStateEventData"
          },
          {
            "type": "object",
            "title": "eventData de lista de motoristas autorizados",
            "required": [
              "status",
              "drivers_added",
              "drivers_removed"
            ],
            "properties": {
              "status": {
                "type": "string",
                "enum": [
                  "inactive",
                  "pending",
                  "active"
                ],
                "description": "Status **global** da lista, derivado dos **identificadores** autorizados (chaveiro iButton, cartão RFID) — não dos motoristas:\n\n- `inactive` — nenhum identificador autorizado configurado no\n  dispositivo.\n\n- `pending` — mudança em propagação: o app pediu uma adição ou remoção\n  que o dispositivo ainda não confirmou.\n\n- `active` — pelo menos um identificador autorizado está confirmado no\n  dispositivo. Um identificador sem motorista associado já leva o status\n  a `active`, e nesse caso `drivers_added` vem vazio.",
                "example": "pending"
              },
              "drivers_added": {
                "type": "array",
                "description": "Motoristas **adicionados** desde o último evento enviado ao seu endpoint — é a diferença incremental, não a lista completa de autorizados. Identificadores físicos sem motorista associado no momento do evento não aparecem aqui. Pode vir vazio quando o evento foi disparado puramente por uma transição de `status`.\n\n**Atenção ao `snake_case`:** este campo e `drivers_removed` são os únicos do payload fora do padrão `camelCase`.",
                "items": {
                  "type": "string",
                  "format": "uuid"
                },
                "example": [
                  "d1234567-0000-0000-0000-000000000001"
                ]
              },
              "drivers_removed": {
                "type": "array",
                "description": "Motoristas **removidos** desde o último evento enviado ao seu endpoint, nas mesmas regras de `drivers_added`.",
                "items": {
                  "type": "string",
                  "format": "uuid"
                },
                "example": [
                  "d7654321-0000-0000-0000-000000000002"
                ]
              }
            }
          }
        ]
      },
      "EventEnvelope": {
        "type": "object",
        "title": "Envelope do evento",
        "description": "Envelope comum a todos os eventos de webhook da Cobli. O corpo da requisição `POST` é sempre este objeto — o que varia entre os tipos é o conteúdo de `eventData`.",
        "required": [
          "eventId",
          "eventTime",
          "eventType",
          "eventData"
        ],
        "properties": {
          "eventId": {
            "type": "string",
            "format": "uuid",
            "description": "Identificador **determinístico** do evento, derivado de `fleetId + signatureId + deviceId + eventType + eventTime`. Nos eventos de rota e parada o identificador do recurso (`routeId` ou `activityId`) também entra na derivação, para que dois recursos encerrados no mesmo milissegundo não colidam.\n\nO mesmo evento sempre produz o mesmo `eventId` — em retentativas, em retransmissões e na recuperação via `GET /public/v2/events`. **Use como chave de idempotência.**",
            "example": "7decdf99-283d-4c70-9b95-a3b3f896e9b9"
          },
          "eventTime": {
            "type": "string",
            "format": "date-time",
            "description": "Momento em que o evento ocorreu no dispositivo, em ISO 8601 UTC.",
            "example": "2024-03-15T10:23:07Z"
          },
          "eventType": {
            "type": "string",
            "description": "Tipo do evento.",
            "example": "geofence_in"
          },
          "eventData": {
            "type": "object",
            "description": "Dados específicos do tipo de evento."
          }
        }
      },
      "BaseEventData": {
        "type": "object",
        "title": "Campos comuns do eventData",
        "description": "Campos de telemetria presentes em todos os eventos de escopo de dispositivo.\n\n**Ausente e `null` não são a mesma coisa, e a regra muda por família de evento.** Em `geofence_in`/`geofence_out`, nos 11 de câmera, nos dois de velocidade e nos quatro de rota e parada, o campo sem dado é **omitido**. Em `ignition_on`, `ignition_off`, `position`, `position_sleep` e nos três `battery_external_*`, o campo sem dado vem **presente com valor `null`** — exceto `cobliId`, `speedInKmh`, `licensePlate` e `networkSignal`, que são omitidos em qualquer tipo. `fleetId` é sempre preenchido na entrega, e por isso segue em `required`. Projete o integrador para tolerar as duas formas em todo campo opcional.",
        "required": [
          "deviceId",
          "vehicleId",
          "fleetId"
        ],
        "properties": {
          "deviceId": {
            "type": "string",
            "description": "Identificador do dispositivo rastreador.",
            "example": "879797465464874"
          },
          "vehicleId": {
            "type": "string",
            "format": "uuid",
            "description": "Identificador do veículo.",
            "example": "05009b4a-bed3-4431-955a-4c3e80dc6697"
          },
          "fleetId": {
            "type": "string",
            "format": "uuid",
            "description": "Identificador da frota.",
            "example": "cf3f1990-2ce3-4ed9-85c5-9a528295ecfe"
          },
          "licensePlate": {
            "type": "string",
            "description": "Placa do veículo. Sempre **omitida** quando o veículo não tem placa cadastrada — nunca `null`.",
            "example": "ABC1D23"
          },
          "cobliId": {
            "type": "string",
            "description": "Identificador alfanumérico de 4 caracteres do dispositivo, o mesmo impresso na etiqueta do equipamento. Sempre omitido quando indisponível — nunca `null`.",
            "example": "R875"
          },
          "driverId": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "Motorista identificado no veículo no momento do evento. Omitido — ou `null`, conforme a família do evento — quando nenhum motorista estava identificado.",
            "example": "d1234567-0000-0000-0000-000000000001"
          },
          "latitude": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Latitude no momento do evento.",
            "example": -23.55052
          },
          "longitude": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "description": "Longitude no momento do evento.",
            "example": -46.633308
          },
          "heading": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0,
            "maximum": 360,
            "description": "Direção do veículo em graus, medida a partir do norte.",
            "example": 90
          },
          "speedInKmh": {
            "type": "number",
            "format": "double",
            "description": "Velocidade do veículo em km/h no momento do evento. Sempre omitido quando indisponível — nunca `null`.",
            "example": 45.2
          },
          "ignition": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "ON",
              "OFF",
              null
            ],
            "description": "Estado da ignição no momento do evento.",
            "example": "ON"
          },
          "odometer": {
            "type": [
              "number",
              "null"
            ],
            "format": "float",
            "description": "Odômetro em quilômetros. Requer odômetro inicial cadastrado no veículo; em dispositivos com rede CAN o valor é lido diretamente do barramento.",
            "example": 45230.5
          },
          "batteryVoltage": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "Tensão da bateria externa em milivolts.",
            "example": 12450
          },
          "fuelLevel": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "Nível de combustível, disponível apenas em dispositivos com rede CAN. **A unidade muda por tipo de evento:** em `position`, `position_sleep`, `ignition_on` e `ignition_off` é o **percentual do tanque** (a maioria das leituras fica entre 0 e 100, com valores fora dessa faixa ocorrendo esporadicamente); em `battery_external_low`, `battery_external_disconnected` e `battery_external_reconnected` é **mililitros**.",
            "example": 68
          },
          "rpm": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "Rotação do motor. Disponível apenas em dispositivos com rede CAN.",
            "example": 1800
          },
          "connectionType": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "UNKNOWN",
              "GSM",
              "THREE_G",
              "FOUR_G_LTE",
              "LTE_CATM1",
              "LTE_NB1",
              "WIFI",
              null
            ],
            "description": "Tipo de rede usada pelo dispositivo para transmitir o evento.",
            "example": "FOUR_G_LTE"
          },
          "networkSignal": {
            "type": "integer",
            "description": "Intensidade do sinal da rede celular no **índice CSQ** do 3GPP TS 27.007 §8.5: inteiro de **0 a 31**, em que **valores maiores indicam sinal mais forte** (`0` ≈ −113 dBm ou menos, `31` ≈ −51 dBm ou mais). O valor `99` significa \"desconhecido ou não detectável\". Não é dBm — não compare com limiares negativos. Sempre omitido quando o dispositivo não reporta o dado; nunca `null`.",
            "example": 22
          },
          "numberOfSatellites": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Número de satélites GPS usados na fixação da posição.",
            "example": 12
          },
          "hdop": {
            "type": [
              "number",
              "null"
            ],
            "format": "float",
            "description": "Diluição horizontal de precisão do GPS. Valores menores indicam maior precisão.",
            "example": 0.9
          }
        }
      },
      "GeofenceEventData": {
        "allOf": [
          {
            "$ref": "#/components/schemas/BaseEventData"
          },
          {
            "type": "object",
            "title": "eventData de ponto de interesse",
            "properties": {
              "geofenceId": {
                "type": "string",
                "format": "uuid",
                "description": "Identificador do ponto de interesse cruzado.",
                "example": "59e88bca-d3b9-4980-95a9-421fe2ffb275"
              },
              "name": {
                "type": "string",
                "description": "Nome do ponto de interesse.",
                "example": "MEU LOCAL DE INTERESSE"
              },
              "address": {
                "type": "string",
                "description": "Endereço cadastrado do ponto de interesse.",
                "example": "Rua Lourenço Marques, 297, São Paulo - SP, 04547-100"
              }
            }
          }
        ]
      },
      "IgnitionEventData": {
        "allOf": [
          {
            "$ref": "#/components/schemas/BaseEventData"
          },
          {
            "type": "object",
            "title": "eventData de ignição",
            "description": "Não acrescenta campos aos comuns. O estado resultante da transição está em `ignition`."
          }
        ]
      },
      "PositionEventData": {
        "allOf": [
          {
            "$ref": "#/components/schemas/BaseEventData"
          },
          {
            "type": "object",
            "title": "eventData de posição",
            "description": "Não acrescenta campos aos comuns. Os campos de rede CAN (`rpm`, `fuelLevel`) aparecem apenas em dispositivos com barramento."
          }
        ]
      },
      "SpeedAlertStartEventData": {
        "allOf": [
          {
            "$ref": "#/components/schemas/BaseEventData"
          },
          {
            "type": "object",
            "title": "eventData de início de excesso de velocidade",
            "required": [
              "speedInKmh",
              "speedLimitInKmh",
              "severity"
            ],
            "properties": {
              "speedLimitInKmh": {
                "type": "number",
                "format": "double",
                "description": "Limite de velocidade vigente que foi ultrapassado.",
                "example": 80
              },
              "severity": {
                "type": "string",
                "description": "Severidade do alerta, derivada de quanto o limite foi ultrapassado.",
                "example": "HIGH"
              }
            }
          }
        ]
      },
      "SpeedAlertEndEventData": {
        "allOf": [
          {
            "$ref": "#/components/schemas/SpeedAlertStartEventData"
          },
          {
            "type": "object",
            "title": "eventData de fim de excesso de velocidade",
            "required": [
              "startTime",
              "durationAboveInMillis"
            ],
            "properties": {
              "startTime": {
                "type": "string",
                "format": "date-time",
                "description": "Momento em que o alerta começou — igual ao `eventTime` do `alert_driven_over_speed` correspondente. Use `deviceId` + `startTime` para correlacionar os dois eventos.",
                "example": "2024-03-15T14:30:00Z"
              },
              "durationAboveInMillis": {
                "type": "integer",
                "format": "int64",
                "description": "Duração total acima do limite, em milissegundos.",
                "example": 90000
              }
            }
          }
        ]
      },
      "BatteryExternalLowEventData": {
        "allOf": [
          {
            "$ref": "#/components/schemas/BaseEventData"
          },
          {
            "type": "object",
            "title": "eventData de bateria externa baixa",
            "required": [
              "batteryVoltageThresholdMv"
            ],
            "properties": {
              "batteryVoltageThresholdMv": {
                "type": "integer",
                "description": "Threshold configurado para a frota no momento do disparo, em milivolts. Compare com `batteryVoltage` para saber a margem.",
                "example": 11500
              },
              "voltageRegime": {
                "type": "string",
                "enum": [
                  "LIGHT",
                  "HEAVY"
                ],
                "description": "Sistema elétrico do veículo: `LIGHT` para 12 V, `HEAVY` para 24 V. Determina qual threshold da frota foi aplicado.",
                "example": "LIGHT"
              }
            }
          }
        ]
      },
      "BatteryExternalConnectionEventData": {
        "allOf": [
          {
            "$ref": "#/components/schemas/BaseEventData"
          },
          {
            "type": "object",
            "title": "eventData de conexão da bateria externa",
            "description": "Não acrescenta campos aos comuns. `batteryVoltage` traz a tensão lida no momento da desconexão ou da reconexão."
          }
        ]
      },
      "CameraEventData": {
        "allOf": [
          {
            "$ref": "#/components/schemas/BaseEventData"
          },
          {
            "type": "object",
            "title": "eventData de evento de câmera",
            "description": "Não acrescenta campos aos comuns. **`rpm` e `fuelLevel` nunca estão presentes** — a câmera não tem acesso ao barramento CAN. `odometer` aparece quando há odômetro inicial cadastrado no veículo."
          }
        ]
      }
    },
    "responses": {
      "WebhookAck": {
        "description": "Evento aceito. Responda `2xx` em até **5 segundos** — enfileire e processe de forma assíncrona se o seu processamento for demorado. Nenhuma retentativa é feita."
      },
      "WebhookRejected": {
        "description": "Evento rejeitado de forma permanente — use para assinatura HMAC inválida ou payload malformado. A Cobli trata `4xx` como falha definitiva e **não retenta**, com duas exceções: `429` (ver abaixo) e `401` em assinaturas com Bearer auth habilitado, em que a Cobli renova o token e retenta. Não devolva `4xx` para um `eventType` que você não espera: ignore-o e responda `2xx`."
      },
      "WebhookThrottled": {
        "description": "Limite de vazão atingido no seu lado. A Cobli retenta respeitando o header `Retry-After` quando presente, **limitado a 15 segundos** — valores maiores são truncados. Sem o header, ou com ele no formato HTTP-date, aplica o backoff exponencial padrão.",
        "headers": {
          "Retry-After": {
            "description": "Segundos a aguardar antes da próxima tentativa. Apenas o formato numérico (`delay-seconds`) é interpretado; valores acima de 15 são truncados para 15.",
            "schema": {
              "type": "integer",
              "example": 10
            }
          }
        }
      },
      "WebhookServerError": {
        "description": "Falha temporária no seu lado. A Cobli faz até **5 tentativas** no total, com backoff exponencial entre elas — **2 s → 4 s → 8 s → 15 s** —, jitter de ±20 % e teto de 15 s por intervalo. O mesmo vale para timeout: sem resposta em 5 segundos."
      }
    }
  },
  "x-tagGroups": [
    {
      "name": "Frota",
      "tags": [
        "Veículos",
        "Motoristas",
        "Dispositivos",
        "Grupos",
        "Locais de interesse",
        "Usuários"
      ]
    },
    {
      "name": "Monitoramento",
      "tags": [
        "Monitoramento"
      ]
    },
    {
      "name": "Trajetos",
      "tags": [
        "Trajetos"
      ]
    },
    {
      "name": "Segurança",
      "tags": [
        "Velocidade",
        "Modo de condução"
      ]
    },
    {
      "name": "Análises",
      "tags": [
        "Produtividade"
      ]
    },
    {
      "name": "Relatórios",
      "tags": [
        "Relatórios"
      ]
    },
    {
      "name": "Manutenção",
      "tags": [
        "Manutenção"
      ]
    },
    {
      "name": "Serviços e Entregas",
      "tags": [
        "Serviços e Entregas"
      ]
    },
    {
      "name": "Gastos",
      "tags": [
        "Gastos",
        "Gestão de Combustível",
        "Cartão Combustível"
      ]
    },
    {
      "name": "Despesas",
      "tags": [
        "Despesas"
      ]
    },
    {
      "name": "Multas",
      "tags": [
        "Multas"
      ]
    },
    {
      "name": "Comprovantes",
      "tags": [
        "Comprovantes"
      ]
    },
    {
      "name": "Checklists",
      "tags": [
        "Checklists"
      ]
    },
    {
      "name": "Cobli Cam",
      "tags": [
        "Mídias"
      ]
    },
    {
      "name": "Alertas",
      "tags": [
        "Alertas"
      ]
    },
    {
      "name": "Webhooks",
      "tags": [
        "Webhooks",
        "Eventos de Webhook"
      ]
    }
  ]
}
````