DirectLuzDirectLuzDocs
Ordens de Serviço

Outbound Webhook

Eventos de ciclo de vida da Ordem de Serviço entregues em tempo real.

Esta página descreve o modo Webhook (push). Para o modo alternativo, ver Polling.

A DirectLuz notifica o sistema externo em dois ciclos:

  1. Ciclo do alerta — sempre que uma solicitação inbound é aceita (independentemente de virar OS imediatamente), o sistema externo recebe Alert.Received. Se o alerta for cancelado antes de virar OS, recebe também Alert.Cancelled.
  2. Ciclo da OS — quando o alerta é convertido em Ordem de Serviço, o sistema externo recebe ServiceOrder.Created e todas as transições subsequentes (StatusChanged, Completed, Cancelled).

Esse desenho garante que o parceiro tem feedback contínuo mesmo nos casos em que a cidade configura triagem manual: ele recebe o Alert.Received imediato confirmando o registro, e só depois (quando a equipe operacional triagear) recebe o ServiceOrder.Created correspondente.

O receptor pode optar por consumir apenas os eventos de interesse via enabledEvents, mas todos são enviados por padrão.

Cadastro do endpoint receptor

O parceiro integrador informa à DirectLuz, no momento do cadastro do sistema externo:

ParâmetroDescrição
webhookUrlURL HTTPS de produção que receberá os eventos
webhookSecretSegredo compartilhado utilizado para a assinatura HMAC-SHA256
enabledEventsLista de eventos que o parceiro deseja receber (opcional — padrão: todos)

URL e segredo podem ser atualizados a qualquer momento pelo painel administrativo.

Cabeçalhos enviados pela DirectLuz

CabeçalhoConteúdo
Content-Typeapplication/json; charset=utf-8
User-AgentDirectLuz-Webhook/1.0
X-Event-TypeIdentificador do evento (ex.: ServiceOrder.Completed)
X-Directluz-Signaturesha256=<hex> — HMAC-SHA256 do corpo cru
X-Directluz-TenantIdentificador do tenant emissor
X-Directluz-DeliveryUUID único por tentativa de entrega (varia entre retries)
X-Directluz-Event-IdUUID único do evento (estável entre retries — chave de idempotência no lado receptor)

Eventos cobertos

EventoGatilho
Alert.CancelledAlerta cancelado antes de virar OS (modo triagem manual, descartado pela operação)
ServiceOrder.CreatedAlerta convertido em Ordem de Serviço (imediato se cidade está em AutoCreate; após triagem em ManualTriage)
ServiceOrder.StatusChangedToda transição de status intermediária (OPEN → IN_PROGRESS, IN_PROGRESS → PAUSED, PAUSED → IN_PROGRESS etc.)
ServiceOrder.CompletedOrdem de Serviço concluída pela equipe de campo
ServiceOrder.CancelledOrdem de Serviço cancelada antes da execução

Eventos de Alerta carregam o objeto alert; eventos de OS carregam o objeto serviceOrder. Em ambos os casos, o protocolNumber (protocolo externo enviado originalmente) aparece no nível raiz do evento.

Payload — Alert.Cancelled

{
  "eventId": "4c5d6e7f-8a9b-4c1d-9e2f-3a4b5c6d7e8f",
  "eventType": "Alert.Cancelled",
  "occurredAt": "2026-05-20T17:10:00Z",
  "protocolNumber": "EXT-2026-001234",
  "alert": {
    "id": "f4d2a1b9-3c5e-4a7d-8e1c-9b2f5d6a7c4e",
    "alertNumber": 1042,
    "assetType": "POLE",
    "cancelledAt": "2026-05-20T17:10:00Z",
    "reason": "Solicitação duplicada — já registrada no protocolo EXT-2026-001210"
  }
}

Payload — ServiceOrder.Created

{
  "eventId": "f1a3c2e4-5b7d-4c9a-8d3e-2f6a1b9c4d7e",
  "eventType": "ServiceOrder.Created",
  "occurredAt": "2026-05-20T13:42:05Z",
  "protocolNumber": "EXT-2026-001234",
  "serviceOrder": {
    "id": "8c2b4a1f-3d6e-4b9a-bc2f-5a7d8e1c9b3a",
    "internalProtocol": "OS-00042",
    "assetType": "POLE",
    "status": "OPEN",
    "priority": "Medium",
    "createdAt": "2026-05-20T13:42:05Z"
  }
}

Payload — ServiceOrder.StatusChanged

{
  "eventId": "9c2d3e1f-4a6b-4d8e-9f1a-3b5c7d8e9f0a",
  "eventType": "ServiceOrder.StatusChanged",
  "occurredAt": "2026-05-21T09:00:00Z",
  "protocolNumber": "EXT-2026-001234",
  "serviceOrder": {
    "id": "8c2b4a1f-3d6e-4b9a-bc2f-5a7d8e1c9b3a",
    "internalProtocol": "OS-00042",
    "assetType": "POLE",
    "previousStatus": "OPEN",
    "status": "IN_PROGRESS",
    "changedAt": "2026-05-21T09:00:00Z"
  }
}

Payload — ServiceOrder.Completed

{
  "eventId": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
  "eventType": "ServiceOrder.Completed",
  "occurredAt": "2026-05-21T15:08:42Z",
  "protocolNumber": "EXT-2026-001234",
  "serviceOrder": {
    "id": "8c2b4a1f-3d6e-4b9a-bc2f-5a7d8e1c9b3a",
    "internalProtocol": "OS-00042",
    "assetType": "POLE",
    "status": "COMPLETED",
    "result": "Resolved",
    "closedAt": "2026-05-21T15:08:00Z",
    "slaBreached": false,
    "closure": {
      "categoryCode": "TROCA_LAMPADA",
      "categoryName": "Troca de lâmpada",
      "notes": "Lâmpada substituída e relé testado",
      "location": {
        "latitude": -7.114,
        "longitude": -34.831
      }
    },
    "attachments": [
      {
        "type": "photo",
        "kind": "after",
        "url": "https://blob.directluz.com.br/tenants/{tenant}/os/00042/depois-1.jpg"
      }
    ]
  }
}

Payload — ServiceOrder.Cancelled

{
  "eventId": "7d8e9f0a-1b2c-4d3e-9f4a-5b6c7d8e9f0a",
  "eventType": "ServiceOrder.Cancelled",
  "occurredAt": "2026-05-21T10:30:00Z",
  "protocolNumber": "EXT-2026-001234",
  "serviceOrder": {
    "id": "8c2b4a1f-3d6e-4b9a-bc2f-5a7d8e1c9b3a",
    "internalProtocol": "OS-00042",
    "assetType": "POLE",
    "status": "CANCELLED",
    "cancelledAt": "2026-05-21T10:30:00Z",
    "reason": {
      "code": "DUPLICATE_REQUEST",
      "description": "Protocolo duplicado — atendimento já vinculado a OS-00038"
    }
  }
}

Reentrega e tratamento de falhas

A DirectLuz considera entregue qualquer resposta 2xx recebida em até 30 segundos.

Resposta do receptorComportamento da DirectLuz
2xxEntrega confirmada
4xx (exceto 408 e 429)Falha permanente. O evento é marcado como processado com erro e não é reenviado
408, 429, 5xxFalha transitória. Reentrega agendada com backoff exponencial
Timeout (> 30 s)Falha transitória. Reentrega agendada com backoff exponencial

Política de backoff

TentativaIntervalo mínimo até a próxima
12 minutos
24 minutos
38 minutos
416 minutos
532 minutos
664 minutos
7+120 minutos (teto)

Após 10 tentativas sem sucesso, o evento é movido para a fila interna de mensagens não entregues (DLQ). Reenvios manuais podem ser solicitados via canal de suporte.

Ordenação de eventos

Em cenários de retentativa, é possível que um evento mais recente chegue antes de um evento anterior do mesmo agregado. O receptor deve utilizar occurredAt como referência temporal canônica.

Idempotência no receptor

O cabeçalho X-Directluz-Event-Id (e equivalentemente o campo eventId no corpo) é estável entre tentativas. O receptor deve persistir essa chave e ignorar eventos duplicados.

On this page