Webhooks
⚠️
Webhook delivery is not currently available on the public API. The public surface (/v1/brand/*, /v1/web/*, /v1/brand/ai/*) is fully synchronous — every endpoint returns its result on the same HTTP request, so there’s nothing to notify you about after the fact.
This page documents what webhook delivery will look like when long-running async endpoints (full-site crawl, large batch jobs, scheduled re-extractions) ship. If you have a use case for webhooks today, open an issue so we can prioritize.
What we plan to deliver
When async endpoints ship, the contract will look like:
- You register a webhook endpoint URL on your account.
- You pass
webhookUrl(or scope a webhook to specific event types) when starting an async operation. - We POST a signed JSON payload to your URL when the operation finishes or fails.
Payload shape (proposed)
{
"id": "evt_abc123",
"event": "<event-type>",
"createdAt": "2026-05-28T10:30:00Z",
"data": {
"...": "event-specific fields"
}
}Headers (proposed)
| Header | Description |
|---|---|
X-Orsa-Event | Event type (e.g., crawl.completed) |
X-Orsa-Signature | HMAC SHA-256 signature of the body using your webhook secret |
X-Orsa-Delivery | Unique delivery ID for idempotency |
User-Agent | Orsa-Webhook/1.0 |
Verification (proposed)
import crypto from 'node:crypto';
function verifyOrsaWebhook(
payload: string,
signature: string,
secret: string,
): boolean {
const expected = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected),
);
}In the meantime
For the current synchronous endpoints, the SDK already gives you:
- Per-request timeouts via
RequestOptions.timeout - Cancellation via
RequestOptions.signal(AbortController) - Automatic retry on 429 / 5xx and connection errors
See Error Handling for the full retry contract and the four Orsa*Error classes.