ShvIA

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":

bash
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"]
  }'
CampoNotas
nameobrigatório, até 120 caracteres
promptobrigatório, até 8000 caracteres. O corpo de cada evento é acrescentado a ele como dado
triggerschedule (o padrão), webhook ou email
delivery_targetsobrigató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_aise 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_enabledo padrão é true. Uma rotina que falha 3 vezes seguidas é desligada
webhook_secreto 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:

json
{
  "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_url leva 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 de PUT /api/v1/routines/{id}. Não registre essas respostas inteiras em log.
  • webhook_secret é mostrado uma vez. Se você não enviar webhook_secret na requisição, o servidor cria um e o devolve. Envie "webhook_secret": null para 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.

bash
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"
json
{ "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:

StatusCorpoQuando
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çãoO que faz
GET /api/v1/routineslista 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-nowcoloca uma execução na fila sem um evento. Uma rotina pausada responde 422
POST /api/v1/routines/{id}/rotate-tokendá à rotina uma URL nova. A antiga deixa de funcionar
POST /api/v1/routines/{id}/rotate-secretdá a ela um segredo novo, devolvido uma vez. O antigo deixa de funcionar
GET /api/v1/routines/{id}/runsas últimas 50 execuções
GET /api/v1/routines/blueprintsautomaçõ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": "…"}.