Get notified when things happen. Subscribe to agent events and receive signed HTTP callbacks — message received, message sent, thread created, and more.

What are webhooks?

Webhooks let you receive real-time HTTP notifications when events happen in your organization. When an agent receives a message, sends a reply, or creates a new thread, Ragwalla sends a POST request to your endpoint with event details.

Webhooks are organization-scoped — a single webhook receives events from all projects and agents in the organization.

Quick start

1. Create a webhook

curl -X POST https://myendpoint.ai.ragwalla.com/organizations/org_abc/webhooks \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "My Event Listener",
    "endpoint_url": "https://your-service.com/webhooks/ragwalla",
    "event_subscriptions": ["channel.*"],
    "auto_generate_secret": true
  }'
{
  "id": "whk_Harruxm11YGdrGLv",
  "organizationId": "org_abc",
  "name": "My Event Listener",
  "endpointUrl": "https://your-service.com/webhooks/ragwalla",
  "secretPrefix": "...a1b2",
  "enabled": true,
  "eventSubscriptions": ["channel.*"],
  "retryMaxAttempts": 3,
  "retryBackoffMs": 1000,
  "createdAt": 1710000000,
  "updatedAt": 1710000000,
  "secret": "f47ac10b-58cc-4372-a567-0e02b2c3d479"
}

Save the secret value. It's returned only on creation — you'll need it to verify webhook signatures.

2. Receive events

When a matching event occurs, Ragwalla sends a POST request to your endpoint:

POST /webhooks/ragwalla HTTP/1.1
Content-Type: application/json
X-Webhook-Event: channel.message_received
X-Webhook-Delivery-Id: wdl_mLQjOXOC20BfLFek
X-Webhook-Timestamp: 1710000042
X-Webhook-Signature: sha256=a1b2c3d4e5f6...

{
  "id": "evt_abc123",
  "type": "channel.message_received",
  "organization_id": "org_abc",
  "project_id": "proj_xyz",
  "agent_id": "ag_myagent",
  "timestamp": 1710000042,
  "data": {
    "thread_id": "thread_001",
    "message_id": "msg_456",
    "channel_type": "telegram",
    "sender_id": "user_789"
  }
}

3. Verify the signature

If you configured a secret, verify the HMAC-SHA256 signature before processing:

const crypto = require('crypto');

function verifyWebhook(body, signature, secret) {
  const computed = 'sha256=' + crypto
    .createHmac('sha256', secret)
    .update(body)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(computed)
  );
}

// In your request handler:
const signature = req.headers['x-webhook-signature'];
const isValid = verifyWebhook(req.rawBody, signature, process.env.WEBHOOK_SECRET);
import hmac
import hashlib

def verify_webhook(body: bytes, signature: str, secret: str) -> bool:
    computed = 'sha256=' + hmac.new(
        secret.encode(), body, hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(signature, computed)

Respond with any 2xx status code to acknowledge receipt. Non-2xx responses trigger retries.


Event subscriptions

Event subscriptions use glob-style patterns to match event types:

Pattern Matches
* All events
channel.* All channel events
agent.* All agent events
channel.message_received Only that specific event

You can subscribe to multiple patterns:

{
  "event_subscriptions": ["channel.message_received", "channel.message_sent"]
}

Available events

Event Fires when
channel.message_received Agent receives a message from a channel
channel.message_sent Agent sends a reply to a channel
channel.thread_created A new conversation thread is created
channel.conversation_reset A user resets their conversation (via /new)
agent.created A new agent is created

Event payload — channel events:

{
  "id": "evt_abc123",
  "type": "channel.message_received",
  "organization_id": "org_abc",
  "project_id": "proj_xyz",
  "agent_id": "ag_myagent",
  "timestamp": 1710000042,
  "data": {
    "thread_id": "thread_001",
    "message_id": "msg_456",
    "channel_type": "telegram",
    "sender_id": "user_789"
  }
}

Retry behavior

Failed deliveries are retried with exponential backoff:

Attempt Delay
1 Immediate
2 retry_backoff_ms (default: 1s)
3 retry_backoff_ms × 2 (default: 2s)

After retry_max_attempts failures (default: 3), the delivery is marked as failed.

You can configure retry behavior per webhook:

{
  "retry_max_attempts": 5,
  "retry_backoff_ms": 2000
}
  • retry_max_attempts: 0–10 (0 disables retries)
  • retry_backoff_ms: 100–60000 milliseconds

Managing webhooks

List webhooks

curl https://myendpoint.ai.ragwalla.com/organizations/org_abc/webhooks \
  -H "Authorization: Bearer $API_KEY"
{
  "webhooks": [
    {
      "id": "whk_Harruxm11YGdrGLv",
      "organizationId": "org_abc",
      "name": "My Event Listener",
      "endpointUrl": "https://your-service.com/webhooks/ragwalla",
      "secretPrefix": "...a1b2",
      "enabled": true,
      "eventSubscriptions": ["channel.*"],
      "retryMaxAttempts": 3,
      "retryBackoffMs": 1000,
      "createdAt": 1710000000,
      "updatedAt": 1710000000
    }
  ]
}

The raw secret is never returned after creation. Only the secretPrefix (last 4 characters) is shown.

Get a webhook

curl https://myendpoint.ai.ragwalla.com/organizations/org_abc/webhooks/whk_Harruxm11YGdrGLv \
  -H "Authorization: Bearer $API_KEY"

Update a webhook

curl -X PUT https://myendpoint.ai.ragwalla.com/organizations/org_abc/webhooks/whk_Harruxm11YGdrGLv \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Updated Listener",
    "event_subscriptions": ["*"],
    "enabled": false
  }'

All fields are optional — only the ones you include are updated:

Field Description
name Display name
endpoint_url Delivery URL
enabled true to receive events, false to pause
event_subscriptions Event patterns to match
retry_max_attempts Max delivery attempts (0–10)
retry_backoff_ms Backoff between retries (100–60000)
secret New HMAC secret (min 16 characters)
auto_generate_secret Set true to rotate to a new generated secret

Disable a webhook

curl -X PUT https://myendpoint.ai.ragwalla.com/organizations/org_abc/webhooks/whk_Harruxm11YGdrGLv \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "enabled": false }'

Disabled webhooks stop receiving deliveries but are not deleted. Re-enable with "enabled": true.

Delete a webhook

curl -X DELETE https://myendpoint.ai.ragwalla.com/organizations/org_abc/webhooks/whk_Harruxm11YGdrGLv \
  -H "Authorization: Bearer $API_KEY"
{ "ok": true }

Rotate a secret

curl -X PUT https://myendpoint.ai.ragwalla.com/organizations/org_abc/webhooks/whk_Harruxm11YGdrGLv \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "auto_generate_secret": true }'

The new secret is returned in the response. Update your verification code before the next delivery.


Delivery history

Inspect delivery attempts for a webhook:

curl "https://myendpoint.ai.ragwalla.com/organizations/org_abc/webhooks/whk_Harruxm11YGdrGLv/deliveries?limit=10" \
  -H "Authorization: Bearer $API_KEY"
{
  "deliveries": [
    {
      "id": "wdl_mLQjOXOC20BfLFek",
      "webhookId": "whk_Harruxm11YGdrGLv",
      "eventType": "channel.message_received",
      "status": "delivered",
      "attempts": 1,
      "maxAttempts": 3,
      "responseStatus": 200,
      "responseBody": "{\"received\":true}",
      "error": null,
      "createdAt": 1710000042,
      "completedAt": 1710000043
    },
    {
      "id": "wdl_xNpQrSt12UvWxYzA",
      "webhookId": "whk_Harruxm11YGdrGLv",
      "eventType": "channel.message_sent",
      "status": "failed",
      "attempts": 3,
      "maxAttempts": 3,
      "responseStatus": 500,
      "responseBody": "Internal Server Error",
      "error": "HTTP 500: Server Error",
      "createdAt": 1710000100,
      "completedAt": 1710000108
    }
  ]
}
Field Description
status pending, delivered, or failed
attempts Number of delivery attempts made
responseStatus HTTP status code from your endpoint
responseBody First 1,000 characters of your endpoint's response
error Error message if delivery failed
nextRetryAt Timestamp of next retry attempt (if pending)

Secrets and security

  • Signing: Every delivery includes an X-Webhook-Signature header (HMAC-SHA256) when a secret is configured
  • One-time reveal: The raw secret is returned only at creation or rotation — it's never retrievable afterward
  • Encryption at rest: Secrets are envelope-encrypted (AES-256-GCM) in the database
  • Prefix display: API responses show only the last 4 characters (secretPrefix) for identification

If you lose your secret, rotate it with auto_generate_secret: true and update your verification code.


API reference summary

Method Endpoint Description
POST /organizations/:orgId/webhooks Create a webhook
GET /organizations/:orgId/webhooks List webhooks
GET /organizations/:orgId/webhooks/:id Get a webhook
PUT /organizations/:orgId/webhooks/:id Update a webhook
DELETE /organizations/:orgId/webhooks/:id Delete a webhook
GET /organizations/:orgId/webhooks/:id/deliveries List delivery history