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

# Referência técnica do Webhook

> Formato do payload, headers, eventos e exemplos de código para integrar o Webhook do IPBoX

> Se você ainda não sabe o que é ou como cadastrar um webhook, veja
> primeiro o [guia de Webhooks](/guides/webhooks).

## Visão geral

* **Método**: `POST`
* **Content-Type**: `application/json`
* **Entrega**: em tempo real — assim que o evento acontece no IPBoX
* **Tentativas**: **uma única tentativa** por evento, com timeout de
  5 segundos. Não há retry automático em caso de falha — seu endpoint
  precisa responder rápido e com um status `2xx` para confirmar o
  recebimento.

## Headers enviados

| Header             | Sempre enviado?   | Descrição                                                                                                                    |
| ------------------ | ----------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `Content-Type`     | Sim               | Sempre `application/json`                                                                                                    |
| `X-Webhook-Secret` | Só se configurado | Valor exato do campo **Secret** cadastrado no webhook — veja [Validando a origem da chamada](#validando-a-origem-da-chamada) |

## Formato do payload

Todo evento chega com esse formato base:

```json theme={null}
{
  "estado": "string",
  "t": 1725650000,
  "evento": "agente.login",
  "usuario_id": 42
}
```

* `estado`: estado interno do agente no momento do evento
  (`online`, `offline`, `paused`, `busy` ou `ringing`)
* `t`: timestamp Unix (segundos) de quando o evento foi gerado
* `evento`: código do evento — é este campo que você usa para saber
  qual dos eventos marcados no cadastro está chegando
* `usuario_id`: ID do agente no IPBoX

Alguns eventos trazem campos extras, além desses quatro (ver tabela
abaixo).

## Catálogo de eventos

| Código (`evento`)  | Quando dispara                               | Campos extras no payload                                                                                               |
| ------------------ | -------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| `agente.login`     | Agente faz login                             | —                                                                                                                      |
| `agente.logout`    | Agente faz logout                            | —                                                                                                                      |
| `agente.pause_in`  | Agente entra em pausa                        | `pausa_id`, `udate`, e opcionalmente `durmax`/`durmin` (limites de duração da pausa, em segundos, quando configurados) |
| `agente.pause_out` | Agente sai da pausa                          | — (`estado` pode vir `online` ou `busy`, dependendo se o agente já tinha uma ligação em andamento)                     |
| `agente.busy`      | Agente entra em uma ligação                  | `udate`                                                                                                                |
| `agente.ringing`   | Telefone do agente está tocando              | —                                                                                                                      |
| `agente.online`    | Ligação terminou / agente disponível de novo | —                                                                                                                      |

### Exemplos de payload

<AccordionGroup>
  <Accordion title="agente.login">
    ```json theme={null}
    {
      "estado": "paused",
      "t": 1725650000,
      "evento": "agente.login",
      "usuario_id": 42
    }
    ```
  </Accordion>

  <Accordion title="agente.logout">
    ```json theme={null}
    {
      "estado": "offline",
      "t": 1725650500,
      "evento": "agente.logout",
      "usuario_id": 42
    }
    ```
  </Accordion>

  <Accordion title="agente.pause_in">
    ```json theme={null}
    {
      "estado": "paused",
      "t": 1725650100,
      "pausa_id": 3,
      "udate": 1725650100,
      "durmax": 900,
      "evento": "agente.pause_in",
      "usuario_id": 42
    }
    ```
  </Accordion>

  <Accordion title="agente.pause_out">
    ```json theme={null}
    {
      "estado": "online",
      "t": 1725650300,
      "evento": "agente.pause_out",
      "usuario_id": 42
    }
    ```
  </Accordion>

  <Accordion title="agente.busy">
    ```json theme={null}
    {
      "estado": "busy",
      "t": 1725650200,
      "udate": 1725650200,
      "evento": "agente.busy",
      "usuario_id": 42
    }
    ```
  </Accordion>

  <Accordion title="agente.ringing">
    ```json theme={null}
    {
      "estado": "ringing",
      "t": 1725650250,
      "evento": "agente.ringing",
      "usuario_id": 42
    }
    ```
  </Accordion>

  <Accordion title="agente.online">
    ```json theme={null}
    {
      "estado": "online",
      "t": 1725650400,
      "evento": "agente.online",
      "usuario_id": 42
    }
    ```
  </Accordion>
</AccordionGroup>

## Validando a origem da chamada

Se você preencher o campo **Secret** no cadastro do webhook, toda
chamada chega com o header `X-Webhook-Secret` contendo exatamente esse
valor. Compare o header recebido com o valor que você configurou —
se não bater, rejeite a chamada.

<Warning>
  Esse mecanismo é um **segredo compartilhado simples** (o mesmo valor
  vai em todas as chamadas), não uma assinatura criptográfica do corpo
  da requisição (tipo HMAC). Ele protege contra chamadas de quem não
  conhece o secret, mas não garante que o corpo da requisição não foi
  alterado em trânsito. Use sempre uma URL **HTTPS** para evitar que o
  secret trafegue em texto puro numa rede não confiável.
</Warning>

### Exemplo em PHP

```php theme={null}
<?php
$payload = file_get_contents('php://input');
$secretRecebido = $_SERVER['HTTP_X_WEBHOOK_SECRET'] ?? '';

if ($secretRecebido !== 'SEU_SECRET_AQUI') {
    http_response_code(401);
    exit;
}

$data = json_decode($payload, true);

// $data['evento'], $data['usuario_id'], $data['estado'], $data['t']
// ... seu processamento aqui ...

http_response_code(200);
```

### Exemplo com curl (simulando o recebimento)

```bash theme={null}
curl -X POST "https://seusistema.com/webhook-ipbox" \
  -H "Content-Type: application/json" \
  -H "X-Webhook-Secret: SEU_SECRET_AQUI" \
  -d '{"estado":"paused","t":1725650000,"evento":"agente.login","usuario_id":42}'
```

## Boas práticas

* Responda rápido (idealmente em menos de 1 segundo) e com status
  `2xx` — como não há retry automático, uma resposta lenta ou com
  erro faz você perder aquela notificação.
* Se precisar processar algo demorado a partir do evento, responda
  `200` imediatamente e processe de forma assíncrona no seu lado.
* Trate o campo `evento` como a fonte da verdade sobre o que
  aconteceu — não dependa só do campo `estado`, já que o mesmo valor
  de `estado` pode aparecer em mais de um tipo de evento.
