Webhooks
Receive task.settled callbacks when a task completes settlement (consensus label + on-chain id available).
Registration — POST /v1/webhooks
curl -sS -X POST https://api.asgrefinery.io/v1/webhooks \
-H "Authorization: Bearer $API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"callback_url": "https://example.com/hooks/asg",
"secret": "whsec_...",
"events": ["task.settled"]
}'
events defaults to ["task.settled"] if omitted.
Success (201):
{
"webhook_id": "whk_...",
"callback_url": "https://example.com/hooks/asg",
"events": ["task.settled"],
"active": true
}
Python
import os
from asg_gateway import ASGGatewayClient
client = ASGGatewayClient(os.environ["API_KEY"])
wh = client.register_webhook(
"https://example.com/hooks/asg",
secret="whsec_...",
events=["task.settled"],
)
print(wh["webhook_id"])
warning
For tasks that set callback_url, register a webhook whose callback_url matches so the dispatcher can select the correct signing secret.
Payload (task.settled)
{
"event": "task.settled",
"task_id": "tsk_...",
"consensus_label": "cat",
"confidence": 1.0,
"bsv_txid": "...",
"settled_at": "2026-04-08T21:05:00Z",
"timestamp": "2026-04-08T21:05:01Z"
}
Signature verification
Header: X-ASG-Signature: sha256=<hex> where <hex> is HMAC-SHA256 of the raw JSON body using your webhook secret.
Python
import hmac
import hashlib
def verify_signature(payload: bytes, secret: str, signature: str) -> bool:
expected = "sha256=" + hmac.new(
secret.encode(), payload, hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, signature)
Go
func verifySignature(payload []byte, secret, signature string) bool {
mac := hmac.New(sha256.New, []byte(secret))
mac.Write(payload)
expected := "sha256=" + hex.EncodeToString(mac.Sum(nil))
return hmac.Equal([]byte(expected), []byte(signature))
}
Retry policy
- Up to
WEBHOOK_RETRY_MAXattempts (default 3). - Backoff delays: 1s, 4s, 16s between attempts.
- After exhaustion, the task record may be marked with
webhook_failin storage — no further automatic attempts.
Local testing
- Run a tunnel (ngrok, Cloudflare Tunnel, etc.) to expose
https://...to your local HTTP server. - Point
callback_urlat the public URL. - When Gateway runs in Docker, you may use
http://host.docker.internal:<port>from the container’s perspective (platform-dependent).
List — GET /v1/webhooks
curl -sS -H "Authorization: Bearer $API_KEY" \
https://api.asgrefinery.io/v1/webhooks
Secrets are not returned.
for w in client.list_webhooks():
print(w["webhook_id"], w["callback_url"], w["active"])
Delete — DELETE /v1/webhooks/{id}
Deactivates the webhook (soft delete).
curl -sS -X DELETE -H "Authorization: Bearer $API_KEY" \
https://api.asgrefinery.io/v1/webhooks/whk_xxx
client.delete_webhook("whk_xxx")
404:
{
"error": "webhook not found"
}