Docs · Protocolos
Webhooks de rotinas
Uma rotina é uma automação que pertence à sua conta: ela executa uma instrução, com ou sem um modelo, e entrega o resultado a um ou mais canais. Uma rotina pode começar num horário, num e-mail recebido, ou numa chamada HTTP do seu sistema. Esta página trata da última, e da API de rotinas de que você precisa para configurá-la.
Crie uma rotina que um webhook inicia#
POST/api/v1/routines#
Autenticado com a sua chave de API. Envie "trigger": "webhook":
curl -s "$SHVIA_URL/api/v1/routines" \
-H "Authorization: Bearer $SHVIA_API_KEY" -H "Content-Type: application/json" \
-d '{
"name": "Deploy notes",
"prompt": "Summarize this deployment event for the team in 2 sentences.",
"trigger": "webhook",
"delivery_targets": ["inapp"]
}'| Campo | Notas |
|---|---|
name | obrigatório, até 120 caracteres |
prompt | obrigatório, até 8000 caracteres. O corpo de cada evento é acrescentado a ele como dado |
trigger | schedule (o padrão), webhook ou email |
delivery_targets | obrigatório, de 1 a 5 entradas: inapp, email:<address>, webhook:https://…, e outras que precisam de um canal que você vinculou, como telegram e whatsapp:<number> |
uses_ai | se um modelo processa o evento. O padrão é true. Com false nenhum modelo é chamado: o seu prompt é entregue como está a cada evento, e o corpo do evento é ignorado |
is_enabled | o padrão é true. Uma rotina que falha 3 vezes seguidas é desligada |
webhook_secret | o seu próprio segredo de assinatura, até 128 caracteres. Veja abaixo |
Você pode ter 10 rotinas por padrão. O limite de tamanho de 65536 bytes, os 10 minutos da janela de duplicados e os 30 eventos por minuto também são padrões, e o operador pode mudá-los.
A resposta é 201:
{
"routine": { "id": 1, "name": "Deploy notes", "trigger": "webhook", "is_enabled": true, "webhook_token": "<48 hex characters>" },
"webhook_url": "https://ai.shvia.org/api/v1/hooks/<48 hex characters>",
"webhook_secret": "<64 hex characters>",
"webhook_assinado": true,
"webhook_aviso": null
}O objeto routine está encurtado aqui. webhook_assinado diz se o webhook confere uma assinatura, e webhook_aviso traz um aviso quando não confere. Três coisas importam:
webhook_urlleva um token secreto no caminho, que é a credencial para enviar eventos. Trate a URL inteira como segredo. O host dela é o endereço da própria instalação.- O mesmo token também está em
routine.webhook_token, nesta resposta e em toda resposta dePUT /api/v1/routines/{id}. Não registre essas respostas inteiras em log. webhook_secreté mostrado uma vez. Se você não enviarwebhook_secretna requisição, o servidor cria um e o devolve. Envie"webhook_secret": nullpara criar de propósito um webhook sem assinatura, que então responde a qualquer um que conheça a URL. Um segredo que você mesmo escolhe não é devolvido.
Envie um evento#
POST/api/v1/hooks/{token}#
Nenhuma outra autenticação. O token no caminho identifica a rotina.
- O corpo pode ser qualquer coisa, até 65536 bytes: JSON é passado à rotina com indentação, outro conteúdo como texto, e um corpo vazio conta como um ping.
- O limite é 120 requisições por minuto por endereço, e cada rotina aceita 30 eventos por minuto por padrão. Acima do limite por endereço, a resposta é o simples
{"message": "Too Many Attempts."}.
Assine o corpo#
Quando a rotina tem um segredo, o que é o padrão, cada evento tem de levar um HMAC-SHA256 dos bytes exatos do corpo, em hexadecimal minúsculo, em X-Shvia-Signature. O header X-Hub-Signature-256 também é aceito, então os webhooks do GitHub funcionam como estão. O prefixo sha256= é opcional.
BODY='{"event":"deploy","id":"evt-1"}'
SIG=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "$WEBHOOK_SECRET" -hex | sed 's/^.* //')
curl -s -X POST "$WEBHOOK_URL" \
-H "Content-Type: application/json" \
-H "X-Shvia-Signature: sha256=$SIG" \
-d "$BODY"{ "ok": true, "queued": true, "event_id": "evt-1" }Assine o corpo que você de fato envia. Serializar o JSON de novo muda os bytes e a assinatura deixa de bater.
Duplicados#
Cada evento tem um id, tirado do primeiro destes que estiver presente: os headers X-Event-Id, X-Request-Id, X-Delivery-Id ou X-GitHub-Delivery, depois um id, event_id ou uuid num corpo JSON e, na falta disso, um hash do corpo. O mesmo id é ignorado por 10 minutos por padrão, então uma nova tentativa do seu remetente é segura. A mesma regra faz com que dois eventos diferentes com exatamente o mesmo corpo, e sem id próprio, contem como duplicados nesse intervalo, e dois pings vazios também.
Respostas#
As checagens rodam nesta ordem:
| Status | Corpo | Quando |
|---|---|---|
| 200 | {"ok": true, "ignored": "disabled"} | os webhooks estão desligados nesta instalação. Esta resposta não olha o token |
| 404 | {"error": "not_found", …} | nenhuma rotina tem este token. Um token que não tem de 32 a 64 caracteres hexadecimais minúsculos recebe, em vez disso, o 404 simples do framework |
| 200 | {"ok": true, "ignored": "disabled_routine"} | a rotina está pausada |
| 413 | {"error": "payload_too_large", …} | o corpo passa de 65536 bytes |
| 401 | {"error": "unauthorized", …} | a assinatura está errada ou ausente |
| 200 | {"ok": true, "ignored": "duplicate", "event_id": "…"} | um evento com este id foi visto nos últimos 10 minutos |
| 200 | {"ok": true, "ignored": "rate_limited"} | a rotina recebeu mais de 30 eventos num minuto |
| 200 | {"ok": true, "queued": true, "event_id": "…"} | aceito |
O evento chega à rotina como dado, não como instrução: o corpo de um evento é embrulhado como conteúdo não confiável, e o seu prompt continua sendo a instrução.
Gerencie as rotinas#
Todos estes pedem a sua chave de API e só alcançam as suas próprias rotinas. A rotina de outra pessoa é um 404.
| Requisição | O que faz |
|---|---|
GET /api/v1/routines | lista as suas rotinas. Nunca mostra um segredo nem um token |
PUT /api/v1/routines/{id} | altera uma rotina. {"webhook_secret": null} remove a assinatura |
DELETE /api/v1/routines/{id} | apaga |
POST /api/v1/routines/{id}/run-now | coloca uma execução na fila sem um evento. Uma rotina pausada responde 422 |
POST /api/v1/routines/{id}/rotate-token | dá à rotina uma URL nova. A antiga deixa de funcionar |
POST /api/v1/routines/{id}/rotate-secret | dá a ela um segredo novo, devolvido uma vez. O antigo deixa de funcionar |
GET /api/v1/routines/{id}/runs | as últimas 50 execuções |
GET /api/v1/routines/blueprints | automações prontas a partir das quais você pode começar |
As falhas de validação são o 422 de sempre, com errors. As recusas que vêm das regras da rotina, como atingir o limite de 10, são {"detail": "…"}.