Outbound Webhooks

Outbound webhooks send HTTP POST notifications for legacy API tasks (source = api) and Agent API Sessions (source = agent_api). Web UI tasks and other task sources are not delivered through this public webhook path.

Events

EventFires when
task.createdA new task is created
task.runningThe agent starts executing or persists an execution block
task.completedTask finishes successfully
task.failedTask fails
task.canceledTask is canceled by user

Create Webhook

POST /v1/webhooks
FieldTypeRequiredDescription
urlstringYesWebhook endpoint URL (HTTPS recommended)
eventsstring[]YesEvents to subscribe to
descriptionstringNoHuman-readable label (max 500 chars)
secretstringNoPre-shared secret (max 500 chars). When set, included as X-Webhook-Secret header in every delivery.
# Webhook without secret
curl -X POST https://api.rebyte.ai/v1/webhooks \
  -H "API_KEY: rbk_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-server.com/webhook",
    "events": ["task.completed", "task.failed"]
  }'

# Webhook with pre-shared secret
curl -X POST https://api.rebyte.ai/v1/webhooks \
  -H "API_KEY: rbk_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-server.com/webhook",
    "events": ["task.completed", "task.failed"],
    "secret": "my-shared-secret-value"
  }'

Response (201):

{
  "id": "880e8400-...",
  "url": "https://your-server.com/webhook",
  "events": ["task.completed", "task.failed"],
  "description": null,
  "hasSecret": true,
  "isActive": true,
  "createdAt": "2026-01-28T12:00:00.000Z"
}

Behavior notes:

  • Duplicate URLs: registering the same URL twice returns the existing webhook (idempotent)
  • Limit: maximum 3 webhooks per organization. The 4th returns limit_exceeded.
  • Secret storage: the secret value is never returned in any response. Only hasSecret: true/false is exposed.

List Webhooks

GET /v1/webhooks

Returns all webhooks for your organization with status info (lastTriggeredAt, failureCount, isActive). Secrets are never exposed.

Get Webhook

GET /v1/webhooks/:id

Delete Webhook

DELETE /v1/webhooks/:id

Returns 204 No Content. Deleted webhooks immediately stop receiving deliveries.

Delivery

When a task event matches a webhook's subscribed events, Rebyte sends an HTTP POST to the webhook URL.

Payload:

{
  "event": "task.completed",
  "taskId": "550e8400-e29b-41d4-a716-446655440000",
  "timestamp": 1706443200,
  "data": {
    "status": "completed",
    "taskUrl": "https://app.rebyte.ai/run/550e8400-...",
    "result": "Created CSV file with 10 Hacker News posts..."
  }
}
  • status — lifecycle status: created, running, completed, failed, or canceled, matching the event name
  • taskUrl — direct link to the task in the Rebyte UI on lifecycle payloads
  • result — final AI output text when one exists on a terminal event; absent from lifecycle task.created and task.running payloads
  • errorMessage — failure detail when one is available

The task.running event name is also used as the envelope for persisted execution blocks. Those deliveries have data.type: "execution_event", an eventType such as thinking, text, tool_use, or tool_result, and a structured payload instead of a lifecycle status.

For a legacy API task, call GET /v1/tasks/:id for current state. For an Agent API Session, the payload taskId is the underlying public Session ID; reconcile through GET /v1/sessions/:id and its Message transcript endpoints.

Delivery headers:

HeaderAlways presentDescription
Content-TypeYesapplication/json
X-Webhook-SignatureYesBase64-encoded RSA-SHA256 signature
X-Webhook-TimestampYesUnix timestamp (seconds)
X-Webhook-SecretOnly if secret configuredThe pre-shared secret value you set on creation

Timeout: deliveries time out after 10 seconds.

Failure handling:

  • Each matching event receives one delivery attempt with no automatic retry
  • A timeout, network error, or non-2xx response may be dropped permanently; there is no delivery queue or durable delivery ledger
  • Delivery is fire-and-forget and never blocks or fails Agent execution
  • Non-2xx responses increment failureCount
  • After 10 consecutive failures, the webhook is automatically disabled (isActive: false)
  • Successful deliveries reset failureCount to 0

Signature Verification

Every delivery is signed with your organization's RSA-2048 key pair, regardless of whether a pre-shared secret is configured.

How it works:

  1. Rebyte concatenates {timestamp}.{body} (e.g., 1706443200.{"event":"task.completed",...})
  2. Signs the string with RSA-SHA256 using your org's private key
  3. Sends the base64-encoded signature in X-Webhook-Signature

Get your public key: retrieve it from the API Playground.

Verification example (Node.js):

const crypto = require('crypto');

function verifyWebhook(rawBody, timestamp, signature, publicKey) {
  const payload = `${timestamp}.${rawBody}`;
  const verifier = crypto.createVerify('RSA-SHA256');
  verifier.update(payload);
  return verifier.verify(publicKey, signature, 'base64');
}

// In your webhook handler:
app.post('/webhook', (req, res) => {
  const rawBody = req.body; // must be raw string, not parsed JSON
  const timestamp = req.headers['x-webhook-timestamp'];
  const signature = req.headers['x-webhook-signature'];

  if (!verifyWebhook(rawBody, timestamp, signature, PUBLIC_KEY)) {
    return res.status(401).send('Invalid signature');
  }

  const event = JSON.parse(rawBody);
  console.log(`Task ${event.taskId}: ${event.event}`);
  res.status(200).send('OK');
});

Verification example (Python):

from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding
import base64

def verify_webhook(raw_body: str, timestamp: str, signature: str, public_key_pem: str) -> bool:
    public_key = serialization.load_pem_public_key(public_key_pem.encode())
    payload = f"{timestamp}.{raw_body}".encode()
    try:
        public_key.verify(
            base64.b64decode(signature),
            payload,
            padding.PKCS1v15(),
            hashes.SHA256()
        )
        return True
    except Exception:
        return False

Two-Layer Security

Webhooks support two independent verification methods that can be used together:

MethodHeaderHow it worksUse case
RSA signatureX-Webhook-SignatureCryptographic proof the payload came from RebyteTamper-proof verification
Pre-shared secretX-Webhook-SecretStatic string you set on creation, echoed back in every deliverySimple shared-secret check

RSA signatures are always present. The pre-shared secret is optional — set it when creating the webhook if you want a simpler verification path.