REST API

Webhooks

Pass a callback_url when creating a task, and Agent delivers the result to your URL as soon as the task finishes. No polling needed.

Enabling webhooks

Add callback_url (and optionally callback_secret) to the POST /api/tasks body:

{
  "assistant_id": 1,
  "callback_url": "https://yourapp.com/hook",
  "callback_secret": "your-secret",
  "input": [{ "type": "text", "text": "What is Laravel?" }]
}

What you receive

Agent delivers a webhook on any terminal status (completed, failed, canceled), and also on interrupted — in that case the body additionally carries pending_tool_calls. The body is the same object that GET /api/tasks/{uuid} returns.

POST callback_url
POST https://yourapp.com/hook
X-Task-Uuid: 550e8400-…
X-Signature: <hmac>          # only if callback_secret is set

{
  "uuid": "550e8400-…",
  "status": "completed",
  "turn": { "output": […], "messages": […], "metadata": { … } },
  "error": null,
  "created_at": "…",
  "completed_at": "…"
}

Verifying the signature

If callback_secret is set, the request carries an X-Signature header — an HMAC-SHA256 of the raw request body. Verify it on your side:

php
$body = file_get_contents('php://input');
$expected = hash_hmac('sha256', $body, $secret);

if (! hash_equals($expected, $_SERVER['HTTP_X_SIGNATURE'] ?? '')) {
    http_response_code(401);   // signature mismatch — reject
    exit;
}

If no callback_secret is set, the X-Signature header isn't sent and there's nothing to verify.

Retries

Delivery goes through a queue (fire-and-forget), with up to 5 attempts and exponential backoff: 10 s, 30 s, 60 s, 120 s. Your endpoint must respond with 2xx, otherwise the attempt counts as failed.

Webhooks and polling aren't mutually exclusive: even with a callback_url, the result is always available via GET /api/tasks/{uuid}.