Webhooks
Event catalog, delivery guarantees, and HMAC signature verification for ASAS webhooks.
الويب هوك
تُرسل أساس أحداثاً إلى نقطة النهاية التي تسجّلها، موقّعةً بـ HMAC للتحقق من مصدرها. تحقّق دائماً من التوقيع قبل الوثوق بالحمولة.
Register an HTTPS endpoint and ASAS will POST events to it — job completions, quota alerts, and more — so you don't have to poll. Every delivery is signed; verify the signature before trusting the payload.
Event catalog
| Event | Fires when |
|---|---|
ping | You send a test event from the dashboard. |
job.completed | An async STT transcription (or RAG indexing) job finishes. |
quota.threshold | Your org crosses 80% / 100% of its monthly credits. |
invoice.finalized | A billing invoice is finalized. |
key.compromised | A leaked key was auto-revoked by secret scanning. |
Payload shape
{
"id": "evt_9f2c1a7b",
"event": "job.completed",
"createdAt": "2026-07-11T09:30:00Z",
"data": { "job_id": "stt_123", "status": "completed" }
}Delivered with two headers:
| Header | Purpose |
|---|---|
ASAS-Signature | HMAC-SHA-256 of ${timestamp}.${rawBody}, hex-encoded. |
ASAS-Timestamp | Unix seconds when the event was signed (replay defense). |
Verify the signature
Compute the HMAC over `${timestamp}.${rawBody}` with your endpoint's signing
secret and compare in constant time. Reject anything older than a few minutes.
import { createHmac, timingSafeEqual } from "node:crypto";
export function verifyAsasWebhook(
rawBody: string,
signatureHeader: string, // ASAS-Signature
timestampHeader: string, // ASAS-Timestamp
secret: string,
): boolean {
// Replay defense: reject stale timestamps (5 minutes).
const age = Math.abs(Date.now() / 1000 - Number(timestampHeader));
if (!Number.isFinite(age) || age > 300) return false;
const expected = createHmac("sha256", secret)
.update(`${timestampHeader}.${rawBody}`)
.digest("hex");
const a = Buffer.from(expected);
const b = Buffer.from(signatureHeader);
return a.length === b.length && timingSafeEqual(a, b);
}Verify against the raw request body, byte for byte. If you parse JSON first and re-serialize, the bytes change and the signature will not match.
Delivery & retries
- Respond
2xxwithin 5 seconds to acknowledge. Anything else is a failure. - Failed deliveries are retried with exponential backoff.
- Deliveries can arrive out of order and more than once — make your handler
idempotent by keying on the event
id. - Inspect recent deliveries and rotate the signing secret from the dashboard.