Webhooks
O Docsbook pode notificar seus sistemas sobre eventos que acontecem dentro de um espaço de trabalho — novo conteúdo indexado, traduções necessárias, perguntas feitas no chat, anomalias de tráfego e muito mais. Cada webhook é tipado: você se inscreve em um dos 18 eventos específicos, e o Docsbook só faz POST para sua URL quando esse evento exato ocorre.
Registrar um webhook e receber suas entregas não gera nenhum custo no saldo do projeto. As entregas que você reproduz ou testa manualmente são contabilizadas como egress, porque cada uma é uma chamada de saída que o Docsbook faz em seu nome.
Como funciona#
- Você registra um webhook com
event_type,urle umsecretopcional. - Quando o evento ocorre, o Docsbook enfileira uma entrega (padrão outbox).
- O worker (cron da Vercel, a cada minuto) envia o corpo JSON via POST para sua URL.
- Nós tentamos novamente até 3 vezes com backoff exponencial (1s, 10s, 60s).
Formato da solicitação#
POST https://your-url.example.com
Content-Type: application/json
User-Agent: Docsbook-Webhooks/1.0
X-Docsbook-Event: content.indexed
X-Docsbook-Signature-256: sha256=<hex hmac of body>
X-Docsbook-Delivery: 12345
X-Docsbook-Attempt: 1{
"event": "content.indexed",
"workspace_id": 42,
"occurred_at": "2026-05-23T12:34:56.000Z",
"data": { /* event-specific payload */ }
}Verificando assinaturas#
import crypto from "node:crypto"
const expected = "sha256=" + crypto.createHmac("sha256", SECRET).update(rawBody).digest("hex")
if (expected !== req.headers["x-docsbook-signature-256"]) reject()Uma resposta 2xx = entregue. Qualquer outra resposta aciona novas tentativas até que o orçamento de tentativas se esgote.
Vendo o que seu espaço de trabalho emite#
O painel Feeds no seu administrador mostra todos os eventos produzidos pelo espaço de trabalho, começando pelos mais recentes — incluindo eventos que nenhum alerta estava monitorando e todas as chamadas de ferramentas MCP feitas contra ele. Você não precisa ter um webhook cadastrado para ver o feed se encher, e esse é o objetivo: é assim que você descobre quais eventos seus documentos realmente emitem antes de decidir sobre o que deseja receber notificações. O feed é atualizado ao vivo — ele se atualiza sozinho a cada poucos segundos enquanto você o consulta, portanto não há um intervalo de tempo para selecionar nem nada que você precise lembrar de recarregar.
Escolher um feed#
A seção Feeds é aberta em uma página de cartões — um por feed, cada um com uma linha dizendo o que ele contém, além de um cartão Crie seu próprio feed no final. Abrir um cartão muda para o próprio feed, sem título ou link de retorno acima dele: você chegou aqui escolhendo um cartão, e a linha Feeds da barra lateral é o caminho de volta para eles.
Os mesmos feeds também são linhas sob essa seção da barra lateral, para alternar entre eles sem sair
daquele que você está lendo — mas essa lista começa fechada. Passe o cursor sobre a linha Feeds e uma
seta substitui o ícone; clique nela para mostrar até cinco feeds, começando pelos abertos mais recentemente, com
Mostrar mais N para o restante, e o Docsbook lembrará se você a deixou aberta na próxima vez que
voltar. O + que cria uma nova lista a partir de um filtro vazio aparece tanto nessa linha quanto como um cartão na
galeria.
Sete feeds vêm integrados, então há algo para abrir na sua primeira visita antes de você salvar qualquer coisa própria: Eventos de leitores (tudo o que as pessoas que leram seus documentos fizeram — páginas lidas, pesquisas realizadas, perguntas feitas à IA, feedback enviado), Traduções (cada idioma gerado, desatualizado ou ainda necessário), Eventos de idioma (para quais idiomas os leitores alternam os documentos), Eventos de chat (perguntas feitas ao assistente de IA, quando ele não encontrou uma resposta, quais respostas receberam uma avaliação negativa), Feedback dos leitores (avaliações negativas e comentários, em uma página ou resposta), Chamadas MCP (todas as chamadas tarifadas feitas por um agente) e Todos os eventos — tudo, sem filtros, por último na lista por ser aquele que você procura quando nenhum dos nomeados se encaixa. Eventos de leitores, Eventos de idioma e Chamadas MCP são feeds para leitura, e não para assinatura, pois nenhum de seus eventos é algo ao qual um alerta possa ser associado; os outros quatro são exatamente aqueles que você indicaria a um notificador. Todos os sete são filtros iniciais, e não listas salvas, portanto não podem ser excluídos e nada pode ser direcionado diretamente a um deles — restrinja um e Salvar como lista o transforma em um feed próprio, que aparece como sua própria linha e é o formato ao qual um alerta pode ser associado.
Lendo o feed#
O feed é dividido em seções diárias, e cada item ocupa uma linha: o avatar do leitor quando um leitor causou o evento (um evento de plano, uso ou MCP não tem ninguém a quem atribuí-lo), um bloco colorido para seu tipo, o nome do evento, o resumo de uma linha e para onde ele foi. O status, o tipo de evento e o destino são exibidos como pequenos glifos, com a palavra disponível a um clique em um popover, para que tudo permaneça em uma linha. Os horários são horas do dia, já que o dia é indicado pelo título da seção acima. Clicar em uma linha a expande no local para mostrar o evento completo — cada tentativa de entrega com sua resposta, a repetição e o payload bruto. Um evento tem um único status, calculado a partir de suas entregas, com o pior resultado prevalecendo:
| Status | Significado |
|---|---|
delivered |
Todos os destinos o aceitaram. |
pending |
Enfileirado; o worker ainda não tentou processá-lo. |
retrying |
Um destino o recusou e ele ainda está dentro do limite de tentativas. |
failed |
Um destino o recusou e o limite de tentativas foi esgotado. |
not sent |
Isso aconteceu, e nenhum alerta estava inscrito nele. |
Chamadas de ferramentas MCP no feed#
O feed também mostra cada chamada de ferramenta MCP feita por um agente neste espaço de trabalho, juntamente com os eventos que seus documentos dispararam. Uma linha por chamada: a ferramenta chamada, se funcionou, quanto tempo levou e quanto custou pelo preço de tabela no cartão de tarifas do MCP. As chamadas com falha indicam isso. As chamadas que não diziam respeito a um projeto específico — descrever o servidor, listar seus projetos, criar um — pertencem à sua conta, e não a um projeto, portanto não aparecem no feed de nenhum projeto.
Elas são exibidas por padrão; não há nada para ativar. No seletor Adicionar evento, elas ficam
em uma seção própria de Chamadas MCP, filtradas pela classe de cobrança da chamada — mcp.read,
mcp.write, mcp.query, mcp.egress, mcp.generate, mcp.agent — e não pelo nome da ferramenta,
que é o eixo que gera custos e que continua funcionando à medida que novas ferramentas são lançadas. O nome da
própria ferramenta aparece em cada linha e em cada payload, portanto filtrar por uma ferramenta específica requer apenas
uma pesquisa no payload. As chamadas gratuitas (get_info, find_skill, find_widget e o restante da descoberta) nunca são contabilizadas
e, portanto, não deixam nenhuma linha.
Uma chamada de ferramenta nunca foi encaminhada para nenhum lugar, portanto aparece como não enviada e, assim como a atividade dos leitores, desaparece no momento em que você filtra por destino ou por status de entrega. Fixar um visitante também a faz desaparecer: um agente portador de um token não é um dos seus leitores, e contar suas chamadas como a navegação de alguém seria incorreto.
Restringir o feed#
Filtre o feed por tipo de evento, status, destino, visitante, uma meta concluída ou texto livre correspondido em qualquer parte do payload — uma única linha de ferramentas acima do feed, sem título acima dela. Cada uma das cinco primeiras facetas é um botão com ícone: passe o mouse sobre ele ou coloque o foco para ver seu nome e, assim que for definida, ela se preenche com o próprio valor; clicar nesse valor permite editá-lo novamente. O texto livre é sua própria caixa de pesquisa sempre visível no final dessa linha, em vez de ser uma faceta que você abre primeiro. Um filtro de visitante fica a um clique de Análises — abra um leitor ali e vá diretamente para tudo o que ele fez — a um clique do próprio avatar de uma linha no feed, ou de um ID colado manualmente. Fixar um leitor amplia o que o feed pesquisa: além dos eventos que seus documentos dispararam, ele busca a atividade do próprio leitor no site — as páginas que ele leu, o que pesquisou, o que perguntou — portanto, um feed fixado é tudo o que esse leitor fez, não apenas as partes que poderiam ter acionado um alerta. Ele também coloca um cartão acima do feed dizendo quem é esse leitor: de onde ele leu, em qual dispositivo, sistema e navegador, o idioma em que leu, a página à qual continua voltando, quanto tempo passou lendo sua documentação no total, as metas que alcançou e quanto vale hoje, além de quanto ainda pode valer. O cartão é apenas para um único leitor fixado, pois um filtro de meta representa uma multidão, e um país e um navegador médios para uma multidão não descrevem ninguém. Salvar um filtro o transforma em uma lista de eventos — portanto, restringir o feed e definir sobre o que você será notificado são o mesmo gesto. Os pings de teste aparecem no feed como qualquer outro evento; uma repetição aparece como outra tentativa sob o evento ao qual pertence. Exportar baixa exatamente o que você está vendo, com os filtros aplicados e sem limite de tempo, como CSV, JSON ou NDJSON — sem limite porque o próprio feed não tem intervalo de tempo: ele é dinâmico, e um arquivo mais restrito que a visualização que copia é pior do que nenhum arquivo. Ele fica no final dessa mesma linha de ferramentas, ao lado de Configurar prompt e Configurar alerta — os três controles que atuam sobre toda a visualização, em vez de sobre um único evento.
Executar um prompt em um feed#
Um alerta encaminha os eventos de um feed para uma pessoa. Configurar prompt, ao lado dele na mesma linha, encaminha-os ao seu assistente: escolha um prompt e ele será executado automaticamente sempre que algo chegar a este feed, sem que ninguém precise acompanhar. O botão exibe uma contagem, para que um feed com algo nele nunca pareça um feed vazio, e cada prompt ativado recebe um chip ao lado dos chips de destino — preenchido enquanto está em execução, vazado enquanto está pausado, com sua última execução na dica de ferramenta.
Clicar em um chip não abre suas configurações. Abre a conversa que o prompt tem mantido: a transcrição do que ele realmente fez na última vez que este feed foi atualizado, no grupo Triggers do assistente. Essa é a única coisa que pode informar que um prompt está funcionando, em vez de apenas estar ativado.
O que monitora um feed monitora um feed salvo, portanto uma visualização que você restringiu, mas ainda não salvou, indica isso e aponta para Salvar como lista. A mesma ativação está disponível do outro lado — o painel Em uma programação ou um evento na própria página de uma ferramenta MCP lista seus feeds acima dos eventos individuais — e excluir um feed desativa o que quer que o monitorasse, em vez de excluir a chamada ativada.
Quanto tudo isso custou#
Cada linha do feed traz um preço, e uma linha de cada vez não é uma coluna que alguém possa somar. Ver uso no cartão de saldo na barra lateral troca o fluxo pela soma: em que o dinheiro deste projeto foi gasto durante um período, começando pelo mais caro, em três seções. Isso não fica na própria barra de ferramentas do feed, porque o valor diz respeito ao projeto inteiro, e não ao feed que você está visualizando.
| Seção | Uma linha por | O que o valor representa |
|---|---|---|
| IA & tokens | superfície e modelo | O preço de cada resposta de IA, tradução ou execução de indexação |
| Chamadas de ferramentas MCP | ferramenta | O preço de tabela das chamadas que a ferramenta realmente fez |
| Eventos registrados | tipo de evento | Quanto custa registrar esse tráfego, de acordo com a tabela de preços |
Os dois primeiros são cobrados: esse dinheiro foi descontado do saldo do projeto. O terceiro não é —
os eventos têm preço para que o tráfego não fique invisível, e nada é descontado por eles. Portanto, os dois totais
são exibidos como dois valores sob duas palavras diferentes, e cada seção traz um selo charged
ou not charged, porque um único número cobrindo os três seria uma cobrança por dinheiro que ninguém recebeu.
Escolha um período de 24 horas, 7 dias ou 30 dias. Não há nada mais longo porque não há nada mais longo para consultar: as análises dos leitores são mantidas por 30 dias e o registro de IA é reduzido para corresponder a isso, então um botão de 90 dias responderia por 30 dias com o rótulo errado.
Exportar aqui oferece o detalhamento em si como um CSV — uma linha por modelo, ferramenta ou tipo de evento, com sua contagem e seu custo como um número simples que você pode somar, além de uma coluna informando se aquela linha foi cobrada — bem como os eventos brutos por trás dele, limitados ao período que você está visualizando.
A mesma tela é aberta por Ver uso no aviso de saldo da barra lateral — o cartão que alerta quando este projeto está ficando sem saldo. A recarga fica no bloco Saldo do menu da conta: um responde quanto resta, este responde no que foi gasto.
Notificadores: para onde vão os eventos#
Um notificador é um destino — um canal, sua URL e suas credenciais — e existe separadamente dos eventos que transporta. Você o cria uma vez — Configurar alerta na linha de título ou Novo notificador na parte inferior de Adicionar notificador — e depois o seleciona nas listas de eventos que ele deve atender. Um canal do Slack alimentado por três listas é um único notificador, com um único segredo de assinatura, pausado ou excluído em um só lugar.
Os notificadores que já estão ativos na lista que você está visualizando ficam ao lado dos chips de filtro, como
chips identificados próprios — cada um com a marca real de seu canal, seu nome e paused quando está
desativado. Clicar em um deles abre esse notificador, para que você veja para onde uma lista envia os eventos e possa
alterá-lo sem sair do feed. Um notificador que está ativo em alguma outra lista — ou em nenhuma ainda, que é
como todo novo notificador começa — pode ser acessado no menu Adicionar notificador, onde cada linha tem um
controle de edição ao lado da caixa de seleção.
Desmarque uma lista e o notificador deixará de ser ativado nela; desmarque a última e o destino permanecerá, sem estar associado a nada e sem entregar nada, até que você o aponte para algum lugar novamente. Excluir uma lista de eventos tem o mesmo efeito sobre tudo o que era ativado por ela — uma assinatura nunca é ampliada pela perda de sua lista.
Apenas listas salvas podem ser atendidas: os feeds integrados, incluindo Todos os eventos, são filtros em vez de listas, portanto salve primeiro aquela que deseja como um feed próprio.
Catálogo de eventos#
Um espaço de trabalho do Docsbook emite 18 eventos tipados. Cada linha abaixo nomeia o evento exatamente como ele aparece no cabeçalho X-Docsbook-Event e no campo event do corpo, com os campos carregados pelo seu objeto data.
| Evento | Campos da carga útil |
|---|---|
content.indexed |
pages_count, relations_count, indexed_at |
content.outdated (obsoleto — não é mais disparado automaticamente) |
last_indexed_at, repo_head_sha |
translation.needed |
source_path, language |
translation.completed |
source_path, language, origin |
translation.outdated |
source_path, language, source_hash_changed |
chat.question_asked |
question, answered, chat_id |
chat.no_answer |
question, chat_id |
chat.negative_feedback |
chat_id, question, answer |
search.no_results |
query |
search.popular |
query, count_24h |
traffic.spike (evento avançado) |
path, views, baseline |
traffic.drop (evento avançado) |
path, views, baseline |
feedback.received |
path, rating, comment |
plan.upgraded |
from, to |
plan.downgraded |
from, to |
usage.limit_approaching |
metric (ai|translation), used, limit |
usage.overage_limit_reached |
workspace_id, overage_spent_cents, overage_limit_cents |
mcp.tool_called (evento avançado) |
tool_name, args |
Três dos dezoito são marcados como avançados — traffic.spike, traffic.drop e mcp.tool_called. Cada um é derivado de uma linha de base ou de uma atividade medida, em vez de ser disparado diretamente por uma ação.
Registrando um webhook#
Via REST#
curl -X POST https://docsbook.io/api/webhooks \
-H "Content-Type: application/json" \
-d '{"workspace_id": 42, "event_type": "content.indexed", "url": "https://you.example.com/hook"}'A resposta inclui secret exatamente uma vez — armazene-o.
event_type aceita qualquer uma das grafias de um nome de evento: a forma com pontos usada em toda esta página (content.indexed) ou a forma com sublinhados (content_indexed). Ambas registram a mesma assinatura.
Cabeçalho de autorização opcional#
Alguns receptores (por exemplo, uma URL de acionamento de rotina do Claude Code) exigem seu próprio token bearer em cada solicitação, separado da verificação da assinatura HMAC. Passe
auth_header ao criar o webhook, e o Docsbook o enviará literalmente como o
cabeçalho Authorization em cada entrega:
curl -X POST https://docsbook.io/api/webhooks \
-H "Content-Type: application/json" \
-d '{"workspace_id": 42, "event_type": "content.indexed", "url": "https://you.example.com/hook", "auth_header": "Bearer sk-..."}'Se o valor não tiver espaço, ele será enviado como Bearer <value>; se já contiver
um esquema (por exemplo, Bearer sk-...), será enviado sem alterações.
Via MCP#
Cada evento tem uma ferramenta MCP dedicada, portanto um agente de IA pode se inscrever em um fluxo de notificações específico sem precisar escolher strings:
register_webhook_content_indexed(workspace_id: 42, url: "https://YOUR_ENDPOINT")
register_webhook_translation_needed(repo: "owner/repo", url: "https://YOUR_ENDPOINT")
register_webhook_traffic_spike(workspace_id: 42, url: "https://YOUR_ENDPOINT")Outras ferramentas MCP, com a classe de cobrança na qual cada chamada é contabilizada:
| Ferramenta | Cobrança | O que faz |
|---|---|---|
list_webhooks(workspace_id) |
Leitura | Lista os webhooks registrados no workspace |
unregister_webhook(webhook_id) |
Escrita | Remove uma inscrição |
test_webhook(webhook_id) |
Saída | Enfileira um ping sintético para a URL registrada |
list_webhook_deliveries(webhook_id) |
Análises | Histórico de entregas com status, número de tentativas e payload |
replay_webhook_delivery(delivery_id) |
Saída | Reenvia uma entrega anterior |
endpoints REST#
GET /api/webhooks?workspace_id=X— listarPOST /api/webhooks— criarPATCH /api/webhooks/:id— renomear, pausar/retomar ou redirecionar para outra lista de eventosPOST /api/webhooks/:id/attach—{ "list_id": N }, servir mais uma lista a partir do mesmo destino (mesma URL, mesmo segredo)DELETE /api/webhooks/:id— excluirPOST /api/webhooks/:id/test— testar pingGET /api/webhooks/:id/deliveries— entregas recentesPOST /api/webhook-deliveries/:id/replay— reenfileirar uma entrega existente
Semântica de novas tentativas e falhas#
- O worker é executado a cada minuto por meio do cron da Vercel.
- Uma entrega é tentada até 3 vezes.
- O intervalo de espera é aplicado a partir de
created_atda linha: 1s, 10s, 60s. - Após a 3ª falha →
status = "failed". Usereplay_webhook_deliverypara tentar novamente. - O código de resposta e o corpo (truncado) são armazenados em cada linha de entrega.
Relacionado#
- Referência das ferramentas MCP — as ferramentas
register_webhook_<event>e todas as outras ferramentas no servidor - Visão geral do servidor MCP — conectando um cliente e a tabela de preços com base na qual o feed cobra pelas chamadas
- Referência dos eventos monitorados — as ações do leitor por trás de vários desses eventos
- Visão geral da análise — lendo a mesma atividade como um relatório em vez de um fluxo