Webhooks
HMAC-SHA256 signed webhooks with replay protection. Rotate secrets without downtime.
What it is
Every webhook delivery includes:
X-AIARCO-Timestamp: <unix>— Unix seconds.X-AIARCO-Signature: t=<unix>,v1=<hex>— HMAC-SHA256 of<unix>.<raw-body>using the webhook's signing secret.
Reject any delivery where |now - timestamp| > 300 s to prevent replay. Compute the signature with the raw body — don't parse and re-serialise.
Secrets can be rotated via POST /v1/webhooks/{id}/rotate-secret. The previous secret stays valid for 24 h so you can roll receivers.
When to use it
- Get notified when a training run completes.
- Receive Shield workflow events for downstream automation.
- React to billing events (budget threshold crossed).
Quickstart
asc webhooks create training-done --url https://my-app/hooks/asc --events training.run.completed,training.run.failed
# returns: { id, secret: 'whsec_…' } — store it, you can't see it again# Verify in your receiver
import hmac, hashlib, time
def verify(body: bytes, header: str, secret: str) -> bool:
parts = dict(p.split('=', 1) for p in header.split(','))
ts = int(parts['t'])
if abs(time.time() - ts) > 300: return False
expected = hmac.new(secret.encode(), f'{ts}.'.encode() + body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, parts['v1'])import { createHmac, timingSafeEqual } from 'crypto';
export function verify(body: Buffer, header: string, secret: string): boolean {
const parts = Object.fromEntries(header.split(',').map(p => p.split('=', 2)));
const ts = parseInt(parts.t, 10);
if (Math.abs(Date.now() / 1000 - ts) > 300) return false;
const expected = createHmac('sha256', secret).update(`${ts}.`).update(body).digest('hex');
return timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1));
}Limits & quotas
| Limit | Default | Burst | Notes |
|---|---|---|---|
| Replay window | ±300 s | — | |
| Retry policy | 5 retries, exp. backoff | — | Up to 24 h |
| Delivery timeout | 10 s | — | Respond 2xx within this window |
API surface
POST /v1/webhooks— createPOST /v1/webhooks/{id}/rotate-secret— rotate (24 h grace)GET /v1/webhooks/{id}/deliveries— delivery logPOST /v1/webhooks/{id}/deliveries/{d}/replay— manual replay
Security
All access is authenticated and scoped. See Auth & scopes and Network controls.