GuidesGet StartedWebhooks

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)

HeaderDescription
X-Orsa-EventEvent type (e.g., crawl.completed)
X-Orsa-SignatureHMAC SHA-256 signature of the body using your webhook secret
X-Orsa-DeliveryUnique delivery ID for idempotency
User-AgentOrsa-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.