Extraction webhooks

Configure a webhook URL to receive a POST notification whenever an extraction job reaches completed state, instead of polling the API.

Configuring the webhook

Endpoint: PUT /v2/extract-settings

Two settings control how webhooks are sent:

Field Type Default Description
webhookUrl string | null null URL that receives POST notifications. Set to null to disable.
webhookFormat "json" | "markdown" "json" Format of the request body — JSON object or Markdown document.
import { Exabase } from "@exabase/sdk";

const api = new Exabase({
  apiKey: process.env.EXABASE_API_KEY,
});

await api.extractSettings.updateSettings({
  webhookUrl: "https://your-server.example.com/webhooks/exabase",
  webhookFormat: "json",
});
await api.extractSettings.updateSettings({
  webhookUrl: "https://your-server.example.com/webhooks/exabase",
  webhookFormat: "markdown",
});
curl https://api.exabase.io/v2/extract-settings \
  -X PUT \
  -H 'X-Api-Key: <EXABASE_API_KEY>' \
  -H 'Content-Type: application/json' \
  -d '{
    "webhookUrl": "https://your-server.example.com/webhooks/exabase",
    "webhookFormat": "json"
  }'
curl https://api.exabase.io/v2/extract-settings \
  -X PUT \
  -H 'X-Api-Key: <EXABASE_API_KEY>' \
  -H 'Content-Type: application/json' \
  -d '{
    "webhookUrl": "https://your-server.example.com/webhooks/exabase",
    "webhookFormat": "markdown"
  }'

To disable webhooks set webhookUrl to null.

Checking current settings

Endpoint: GET /v2/extract-settings

const settings = await api.extractSettings.get();
console.log(settings.webhookUrl);
curl https://api.exabase.io/v2/extract-settings \
  -H 'X-Api-Key: <EXABASE_API_KEY>'

Webhook payload

Exabase sends a POST request to your URL with an X-Trace-Id header for correlation. The body format depends on webhookFormat:

  • json (default) — Content-Type: application/json. The body is the full ExtractJob object, identical to what you'd get from GET /v2/extract/{jobId}.
  • markdownContent-Type: text/markdown. The body is a human-readable Markdown document built from the extraction data (see Output formats).

Example JSON payload:

{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "workspaceId": "...",
  "state": "completed",
  "kind": "document",
  "name": "Invoice #1042",
  "extraction": {
    "common": { "mimeType": "application/pdf", "size": 204800 },
    "document": {
      "pages": 2,
      "documentType": "invoice",
      "structured": { "vendor": "Acme Corp", "total": 100.00 }
    }
  }
}

Return any 2xx status code to acknowledge delivery. Non-2xx responses or network timeouts are retried with exponential backoff.

Manual trigger

You can dispatch a webhook for any existing job without reprocessing it. Useful for testing your endpoint or replaying a missed delivery.

Endpoint: POST /v2/extract/{jobId}/webhook/trigger

const { traceId } = await api.extract.triggerWebhook({ jobId: "job-id" });
console.log("dispatched with trace id:", traceId);
curl https://api.exabase.io/v2/extract/<jobId>/webhook/trigger \
  -X POST \
  -H 'X-Api-Key: <EXABASE_API_KEY>'

Webhook logs

Each dispatch attempt is logged. Use the logs to inspect delivery status, response codes, and response bodies.

Endpoints:

const logs = await api.extract.listWebhookLogs({ jobId: "job-id" });

for (const log of logs.items) {
  console.log(log.attemptNumber, log.status, log.statusCode);
}
curl https://api.exabase.io/v2/extract/<jobId>/webhook-logs \
  -H 'X-Api-Key: <EXABASE_API_KEY>'