Webhooks

Webhooks Cobli — Guia de Integração

O que é webhook?

Webhook é uma tecnologia que permite que a Cobli envie uma requisição HTTP POST para a sua aplicação sempre que um evento relevante ocorrer na frota — sem que você precise ficar consultando nossa API. Use webhooks para:

  • Disparar alertas em tempo real (excesso de velocidade, bateria baixa)
  • Integrar rastreamento de frota com sistemas internos
  • Automatizar fluxos a partir de eventos de ignição ou ponto de interesse

Eventos disponíveis

EventoDescrição
geofence_inVeículo entrou em um ponto de interesse
geofence_outVeículo saiu de um ponto de interesse
ignition_onIgnição ligada
ignition_offIgnição desligada
positionPosição periódica do veículo (ignição ligada)
position_sleepPosição periódica do veículo (ignição desligada)
alert_driven_over_speedInício de alerta de excesso de velocidade
end_alert_driven_over_speedFim de alerta de excesso de velocidade
battery_external_lowTensão da bateria externa abaixo do threshold configurado
battery_external_disconnectedBateria externa desconectada do dispositivo
battery_external_reconnectedBateria externa reconectada ao dispositivo

Alias speed: ao subscrever o tipo "speed", você recebe automaticamente tanto alert_driven_over_speed quanto end_alert_driven_over_speed — os dois eventos são inseparáveis e sempre entregues juntos.


Primeiros passos

  1. Crie um endpoint HTTP que aceite POST com Content-Type: application/json.

    • Responda 2xx em até 5 segundos. Processe de forma assíncrona se necessário.
    • Valide o header X-Cobli-Signature antes de processar (ver Verificação de assinatura).
  2. Cadastre a assinatura no painel Cobli em Configurações → Webhooks.

    • Informe a URL, a chave secreta e os tipos de evento desejados.
  3. Valide a integração — gere um evento de teste (ex: ligue a ignição de um veículo) e confirme que seu endpoint recebe o payload esperado.


Formato dos eventos

Todos os eventos seguem o mesmo envelope:

{
  "eventId"  : "7decdf99-283d-4c70-9b95-a3b3f896e9b9",
  "eventTime": "2024-03-15T10:23:07Z",
  "eventType": "geofence_in",
  "eventData": { }
}
CampoTipoDescrição
eventIdUUIDIdentificador único do evento — use para deduplicação
eventTimeISO 8601 (UTC)Momento em que o evento ocorreu
eventTypestringTipo do evento (ver tabela acima)
eventDataobjetoDados específicos do evento (detalhados abaixo)

Campos comuns em eventData

Todos os eventos incluem os campos abaixo em eventData. Campos opcionais são omitidos quando não disponíveis.

CampoTipoObrigatórioDescrição
deviceIdstringsimIdentificador do dispositivo
vehicleIdUUIDsimIdentificador do veículo
cobliIdstringnãoIdentificador alfanumérico de 4 caracteres do dispositivo (ex: "R875"); presente quando disponível
latitudefloatnãoLatitude no momento do evento
longitudefloatnãoLongitude no momento do evento
headingintnãoDireção em graus (0–360)
ignitionstringnãoEstado da ignição: "ON" ou "OFF"
odometerfloatnãoOdômetro em km. Requer odômetro inicial cadastrado no veículo; para dispositivos com rede CAN, o valor é obtido diretamente pelo dispositivo (odômetro inicial não necessário)
speedInKmhfloatnãoVelocidade no momento do evento (km/h)
batteryVoltagelongnãoTensão da bateria em milivolts
fuelLevellongnãoNível de combustível em mililitros (mL) — disponível apenas em dispositivos com rede CAN
rpmlongnãoRotação do motor (RPM) — disponível apenas em dispositivos com rede CAN
connectionTypestringnãoTipo de rede: GSM, THREE_G, FOUR_G_LTE, WIFI
numberOfSatellitesintnãoNúmero de satélites GPS
hdopfloatnãoPrecisão horizontal do GPS
driverIdUUIDnãoIdentificador do motorista, quando identificado

Verificação de assinatura

Cada requisição inclui o header X-Cobli-Signature com a assinatura HMAC-SHA256 do corpo da requisição, codificada em hexadecimal. Use a secretKey configurada na assinatura para verificar a autenticidade:

import hmac, hashlib

def verificar(secret: str, body: bytes, assinatura: str) -> bool:
    esperado = hmac.new(secret.encode(), body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(esperado, assinatura)

Rejeite requisições sem X-Cobli-Signature válido com status 400. Nunca processe um payload cuja assinatura não pôde ser verificada.


Payload por tipo de evento

GEOFENCE_IN e GEOFENCE_OUT

Disparado quando um veículo entra ou sai de um ponto de interesse cadastrado.

{
  "eventId"  : "7decdf99-283d-4c70-9b95-a3b3f896e9b9",
  "eventTime": "2024-03-15T10:23:07Z",
  "eventType": "geofence_in",
  "eventData": {
    "deviceId"  : "879797465464874",
    "vehicleId" : "05009b4a-bed3-4431-955a-4c3e80dc6697",
    "cobliId"   : "R875",
    "fleetId"   : "cf3f1990-2ce3-4ed9-85c5-9a528295ecfe",
    "latitude"  : -23.764235,
    "longitude" : -46.595110,
    "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
  }
}

Campos adicionais:

CampoTipoDescrição
fleetIdUUIDIdentificador da frota
geofenceIdUUIDIdentificador do ponto de interesse
namestringNome do ponto de interesse
addressstringEndereço do ponto de interesse
speedInKmhfloatVelocidade no momento do cruzamento

IGNITION_ON e IGNITION_OFF

Disparado quando há mudança no estado da ignição do veículo.

{
  "eventId"  : "a1b2c3d4-0000-0000-0000-111122223333",
  "eventTime": "2024-03-15T08:00:00Z",
  "eventType": "ignition_on",
  "eventData": {
    "deviceId"        : "879797465464874",
    "vehicleId"       : "05009b4a-bed3-4431-955a-4c3e80dc6697",
    "cobliId"         : "R875",
    "driverId"        : "d1234567-0000-0000-0000-000000000001",
    "latitude"        : -23.550520,
    "longitude"       : -46.633308,
    "heading"         : 90,
    "ignition"        : "ON",
    "odometer"        : 45230.5,
    "batteryVoltage"  : 12450,
    "connectionType"  : "FOUR_G_LTE"
  }
}

Particularidade: driverId é incluído quando um motorista está associado ao veículo no momento do evento.


POSITION e POSITION_SLEEP

Disparado periodicamente com a posição do veículo (POSITION com ignição ligada, POSITION_SLEEP com ignição desligada). A frequência depende da configuração do dispositivo e do estado do veículo. Também é gerado quando o estado de ignição muda.

{
  "eventId"  : "b2c3d4e5-0000-0000-0000-222233334444",
  "eventTime": "2024-03-15T10:00:00Z",
  "eventType": "position",
  "eventData": {
    "deviceId"           : "879797465464874",
    "vehicleId"          : "05009b4a-bed3-4431-955a-4c3e80dc6697",
    "cobliId"            : "R875",
    "latitude"           : -23.550520,
    "longitude"          : -46.633308,
    "heading"            : 180,
    "speedInKmh"         : 45.2,
    "ignition"           : "ON",
    "odometer"           : 45245.0,
    "numberOfSatellites" : 12,
    "hdop"               : 0.9,
    "rpm"                : 1800,
    "fuelLevel"          : 35000,
    "connectionType"     : "FOUR_G_LTE"
  }
}

Particularidade: POSITION_SLEEP tem os mesmos campos, mas a ignição está desligada ("ignition": "OFF"). Dados de RPM e velocidade geralmente estarão ausentes ou zerados.


ALERT_DRIVEN_OVER_SPEED

Disparado quando um veículo ultrapassa o limite de velocidade configurado. Indica o início do alerta.

{
  "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",
    "cobliId"         : "R875",
    "fleetId"         : "cf3f1990-2ce3-4ed9-85c5-9a528295ecfe",
    "latitude"        : -23.550520,
    "longitude"       : -46.633308,
    "speedInKmh"      : 95.0,
    "speedLimitInKmh" : 80.0,
    "severity"        : "HIGH",
    "driverId"        : "d1234567-0000-0000-0000-000000000001"
  }
}

Campos adicionais:

CampoTipoDescrição
fleetIdUUIDIdentificador da frota
speedInKmhfloatVelocidade atual do veículo
speedLimitInKmhfloatLimite de velocidade configurado
severitystringSeveridade do alerta

END_ALERT_DRIVEN_OVER_SPEED

Disparado quando o veículo volta ao limite de velocidade. Complementa o ALERT_DRIVEN_OVER_SPEED com a duração total do alerta.

{
  "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",
    "cobliId"               : "R875",
    "fleetId"               : "cf3f1990-2ce3-4ed9-85c5-9a528295ecfe",
    "latitude"              : -23.552100,
    "longitude"             : -46.634500,
    "speedInKmh"            : 78.0,
    "speedLimitInKmh"       : 80.0,
    "severity"              : "HIGH",
    "startTime"             : "2024-03-15T14:30:00Z",
    "durationAboveInMillis" : 90000,
    "driverId"              : "d1234567-0000-0000-0000-000000000001"
  }
}

Campos adicionais:

CampoTipoDescrição
fleetIdUUIDIdentificador da frota
startTimeISO 8601 (UTC)Momento em que o alerta iniciou
durationAboveInMillislongDuração total do alerta em milissegundos

Particularidade: use deviceId e fleetId para correlacionar o início e o fim do alerta — o startTime do fim equivale ao eventTime do ALERT_DRIVEN_OVER_SPEED correspondente.


BATTERY_EXTERNAL_LOW

Disparado quando a tensão média da bateria externa cai abaixo do threshold configurado para a frota.

{
  "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",
    "cobliId"                    : "R875",
    "latitude"                   : -23.550520,
    "longitude"                  : -46.633308,
    "ignition"                   : "OFF",
    "batteryVoltage"             : 11200,
    "batteryVoltageThresholdMv"  : 11500,
    "voltageRegime"              : "LIGHT"
  }
}

Campos adicionais:

CampoTipoObrigatórioDescrição
batteryVoltageThresholdMvintsimThreshold configurado no momento do disparo (mV)
voltageRegimestringnãoSistema elétrico do veículo: "LIGHT" (12 V) ou "HEAVY" (24 V)

BATTERY_EXTERNAL_DISCONNECTED

Disparado quando a bateria externa é desconectada do dispositivo.

{
  "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",
    "cobliId"       : "R875",
    "latitude"      : -23.550520,
    "longitude"     : -46.633308,
    "ignition"      : "OFF",
    "batteryVoltage": 0
  }
}

Usa os mesmos campos base de eventData — sem campos adicionais.


BATTERY_EXTERNAL_RECONNECTED

Disparado quando a bateria externa é reconectada ao dispositivo.

{
  "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",
    "cobliId"       : "R875",
    "latitude"      : -23.550520,
    "longitude"     : -46.633308,
    "ignition"      : "OFF",
    "batteryVoltage": 12350
  }
}

Usa os mesmos campos base de eventData — sem campos adicionais.


Retentativas e idempotência

CenárioComportamento
Resposta 2xxEntrega confirmada — sem retentativa
Resposta 4xxFalha permanente — não retentado
Resposta 5xxRetentado automaticamente com backoff exponencial
Timeout (> 5 s)Retentado automaticamente

Use eventId como chave de idempotência. Em caso de retentativa, o mesmo evento pode ser entregue mais de uma vez — armazene os IDs já processados para evitar efeitos duplicados.


Boas práticas

  • Responda rápido, processe depois. Seu endpoint deve responder 2xx em até 5 s. Enfileire o evento e processe em background para evitar timeout.

  • Use eventId como chave de idempotência. Em caso de retentativa, o mesmo evento pode ser entregue mais de uma vez. Armazene os IDs já processados.

  • Valide sempre a assinatura antes de processar o payload — rejeite requests sem X-Cobli-Signature válido com 400.

  • Não retente erros 4xx. O pipeline interpreta 4xx como falha permanente e não fará novas tentativas. Corrija sua integração e aguarde novos eventos.

  • Filtre por eventType no início do handler para ignorar tipos não esperados sem retornar erro.


Formato legado (retrocompatível)

Assinaturas criadas antes da migração para o formato padrão continuam recebendo o payload no formato legado. Esse formato não sofrerá mudanças — a compatibilidade é garantida indefinidamente para assinaturas existentes.

O formato legado é aplicado apenas aos eventos geofence_in e geofence_out.

{
  "event_id"  : "7decdf99-283d-4c70-9b95-a3b3f896e9b9",
  "event_type": "geofence_in",
  "event_time": "2022-09-08 15:47:46",
  "event_data": {
    "fleetId"   : "cf3f1990-2ce3-4ed9-85c5-9a528295ecfe",
    "deviceId"  : "879797465464874",
    "latitude"  : -23.764235,
    "longitude" : -46.595110,
    "geofenceId": "59e88bca-d3b9-4980-95a9-421fe2ffb275",
    "name"      : "MEU LOCAL DE INTERESSE",
    "address"   : "Rua Lourenço Marques, 297, São Paulo - SP, 04547-100"
  }
}

Diferenças em relação ao formato padrão:

AspectoFormato padrãoFormato legado
Chaves do envelopecamelCasesnake_case
eventTime / event_timeISO 8601 (2024-03-15T10:23:07Z)"yyyy-MM-dd HH:mm:ss" (UTC)
vehicleIdpresenteausente
Eventos disponíveistodosapenas