Documentation Menu

Webhooks and Callbacks

An event-driven asynchronous structure used so your system is notified immediately when long-running model operations, pipeline runs, or agent actions requiring human approval complete.

01Why Are Asynchronous Requests Needed?

Complex models such as Birk-Agent-Heavy may run deep data analysis, execute long processes, or coordinate multiple agents, so response times can increase. Instead of limiting your system with HTTP timeouts or making the client wait, you can use webhook architecture.

With the webhook approach, your application starts the job, Birk continues execution in the background, and important status changes are sent to the endpoint you define. The UI does not freeze, the result is not lost if a mobile app moves to the background, and long-running enterprise flows become traceable.

When you provide a webhook_url while starting a request, the result is automatically POSTed to the URL you specify when the job finishes or an intermediate status changes.

02Delivery Flow

01

Start Job

The API request is sent with webhook_url and optional metadata.

02

Accept

Birk queues the job and creates a job_id.

03

Run

The model, agent, or pipeline progresses in the background.

04

Deliver

The result or intermediate event is sent to your webhook endpoint.

03Event Catalog

A webhook is not only a 'job finished' notification. In long-running flows, queued, started, progress, success, failure, and human approval states should be tracked as separate event types.

job.queued

Sent when a long-running job is queued.

Show the user that the job was accepted and start a waiting state in the interface.

job.started

Sent when model or pipeline execution actually starts.

Measure processing time and show live status in an operations panel.

job.progress

Sent when a meaningful intermediate stage completes inside a multi-step pipeline.

Show percentage, stage, or explanation to the user in long analyses.

job.completed

Sent when the job completes successfully.

Fetch the result, update the report screen, or notify the user.

job.failed

Sent when the job cannot complete because of a permanent error.

Record the error state, show an explainable message, and decide whether to retry.

approval.required

Sent when an agent needs human approval for a critical action.

Open an approval screen, create a Slack/Teams notification, or put the task on hold.

04Example Webhook Payload

When the Birk model finishes processing, it sends a JSON structure like the one below to your server. Your server is expected to accept this request and quickly return HTTP 2xx. If long processing is required, enqueue the payload internally and do not keep the webhook request waiting.

JSON / POST
{
  "id": "evt_01J2QZ8R7K9M",
  "event_type": "job.completed",
  "created": 1767326500,
  "delivery_attempt": 1,
  "job": {
    "id": "job_123abc",
    "status": "success",
    "model": "birk-agent-heavy-v1",
    "started_at": "2026-05-02T12:41:04Z",
    "completed_at": "2026-05-02T12:42:18Z"
  },
  "data": {
    "result": {
      "role": "assistant",
      "content": "Analysis completed. The summary you expected..."
    },
    "usage": {
      "prompt_tokens": 1840,
      "completion_tokens": 612,
      "total_tokens": 2452
    }
  },
  "metadata": {
    "customer_id": "cus_7842",
    "workflow": "monthly_sales_review"
  }
}

HTTP method

Birk webhook deliveries are sent to the receiver endpoint as POST requests.

Success response

If the receiver endpoint returns 2xx, the delivery is accepted as successful.

Timeout

If the receiver system does not respond within a reasonable time, the delivery fails and enters the retry plan.

Ordering

Events for the same job are attempted in logical order; the receiver side should still be designed as idempotent.

Redelivery

The same event can be sent again on network errors or 5xx statuses.

05Signature Verification and Security

What you need to verify

Signature

The x-briq-signature header must match the payload.

Time

If x-briq-timestamp is too old, the request should be rejected.

Source

The endpoint should only run over HTTPS.

Replay

The same event_id should not be processed twice.

Node.js / Signature Verification
import crypto from "node:crypto";

function verifyBriqSignature({ rawBody, timestamp, signature, secret }) {
  const signedPayload = `${timestamp}.${rawBody}`;
  const expected = crypto
    .createHmac("sha256", secret)
    .update(signedPayload)
    .digest("hex");

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

06Retry and Idempotency

Webhook delivery can be affected by network conditions. Your receiver must therefore be designed to receive the same event more than once. The critical rule is: the event may arrive again, but business logic must not run again.

Retry

Responses outside 2xx and timeouts can cause redelivery.

Idempotency

event_id or job.id + event_type should be stored as a unique key.

Delayed delivery

Early attempts use short intervals, later attempts use increasing wait time.

Idempotent Processing
async function handleWebhook(event) {
  const alreadyProcessed = await db.webhookEvents.findUnique({
    where: { eventId: event.id }
  });

  if (alreadyProcessed) {
    return { status: 200, body: "already processed" };
  }

  await db.webhookEvents.create({
    data: {
      eventId: event.id,
      type: event.event_type,
      jobId: event.job.id
    }
  });

  await enqueueBusinessWork(event);

  return { status: 200, body: "accepted" };
}

07Receiver Endpoint Example

Next.js Route Handler
export async function POST(request) {
  const rawBody = await request.text();
  const signature = request.headers.get("x-briq-signature");
  const timestamp = request.headers.get("x-briq-timestamp");

  const valid = verifyBriqSignature({
    rawBody,
    signature,
    timestamp,
    secret: process.env.BRIQ_WEBHOOK_SECRET
  });

  if (!valid) {
    return new Response("invalid signature", { status: 401 });
  }

  const event = JSON.parse(rawBody);
  await handleWebhook(event);

  return new Response("ok", { status: 200 });
}

Endpoint behavior

Raw body must be preserved; signature verification must not be done over parsed JSON.
Return 200 OK quickly for accepted events.
If business logic takes a long time, run it in a background queue, not inside the webhook.
Unknown event types should be logged without locking your system.

08Production Checklist

CHECK 01

Your webhook endpoint should be public, but signature verification must be mandatory.

CHECK 02

If the same event_id arrives a second time, the operation must not run again.

CHECK 03

If business logic takes a long time, do not run it inside the webhook request; enqueue it and return a fast 2xx.

CHECK 04

Track payload size, timeout, and error rate as separate metrics.

CHECK 05

Rotate old signature keys on a plan and accept both keys during the transition period.

CHECK 06

For critical events, produce the user-facing message in your product language instead of showing the raw error.

Secret key

The webhook secret should be stored in environment variables and rotated regularly.

Event record

Each event delivery should be recorded with status, attempt count, and error message.

Alarm

If failed deliveries exceed a defined rate, the operations team should be alerted.