Webhook
Webhook endpoints let external systems send events into your agent’s event stream. Each agent can have multiple endpoints for different integrations.
Creating an Endpoint
Section titled “Creating an Endpoint”- Open Agent Settings → Webhooks
- Enter a name (e.g.
youtube-live,discord) - Choose an authentication mode
- Click Create webhook
New webhooks start in testing mode — incoming payloads are stored for preview but no events are created. This lets you verify the data format before going live.
The generated endpoint URL is:
POST /api/ingest/webhook/<webhookId>Testing Mode
Section titled “Testing Mode”When a webhook is in testing mode:
- Send a real payload from your external application to the endpoint URL
- Open the Configure mapping dialog from the webhook card
- Received payloads appear in the Source Payload dropdown (up to 10 most recent)
- Use the visual mapping editor to map incoming fields to event properties
- Review the live preview to verify your mapping produces correct results
- Click Go Live to activate the webhook — subsequent payloads will create events
Testing mode gives you a safe environment to iterate on your mapping configuration without polluting your event stream.
Visual Mapping
Section titled “Visual Mapping”The mapping dialog provides two modes:
Visual Mode (Recommended)
Section titled “Visual Mode (Recommended)”The visual editor shows a split-pane view:
- Left panel — Source Payload: A JSON tree of the received payload. Click any field while a target field is focused to generate the mapping expression automatically.
- Right panel — Target Fields: Five event fields to map:
| Field | Key | Required | Default Template |
|---|---|---|---|
| Platform | platform | No | {{ payload.platform || 'webhook' }} |
| Element | element | No | {{ payload.username || 'external' }} |
| Event Type | event_type | No | {{ payload.event_type || 'message' }} |
| Title | title | Yes | {{ payload.message }} |
| Payload | payload | No | {{ payload }} |
Below the target fields, a live preview shows the resolved values using the currently selected test payload.
Click-to-map workflow:
- Click a target field input to focus it
- Click a node in the JSON tree on the left
- The expression
{{ payload.path.to.field }}is automatically inserted - The live preview updates immediately
Raw Mode
Section titled “Raw Mode”Switch to the Raw editor tab for direct JSON editing. The full mapping is expressed as a JSON object with {{ payload.xxx }} template syntax:
{ "platform": "{{ payload.platform || 'webhook' }}", "element": "{{ payload.username || 'external' }}", "event_type": "{{ payload.event_type || 'message' }}", "title": "{{ payload.message }}", "payload": "{{ payload }}"}Changes sync bidirectionally when switching between tabs.
Template Syntax
Section titled “Template Syntax”payloadrefers to the incoming JSON payloadpayload.path.to.fieldaccesses nested fields (works with objects and arrays, e.g.payload.items.0.name)||chains provide fallback values'literal'values are used as-is{{ payload }}passes the entire payload object
The mapping must produce a non-empty title field. If it doesn’t, the ingest will be rejected with a 422 error.
Authentication Modes
Section titled “Authentication Modes”| Mode | Security | Use Case |
|---|---|---|
open | None | Testing, low-risk internal sources |
api_key | Key in header/query/body | Integrations that can send a key but not sign |
secret | Key-based verification | Production-recommended |
For api_key and secret modes, the key can be provided in any of these locations (checked in order):
Authorization: Bearer <key>headerX-Webhook-Key,X-API-Key, orX-Webhook-Secretheader- Query parameter:
key,api_key,secret, ortoken - JSON body field:
key,api_key,secret, ortoken
This flexibility allows sources that cannot set custom headers (like Social Stream Ninja) to pass the key in the JSON body or query string.
Sensitive Field Stripping
Section titled “Sensitive Field Stripping”When a webhook is in testing mode, authentication-related fields are automatically stripped from stored payloads to avoid leaking credentials in the UI. The following fields are removed by default:
key, api_key, secret, token, password, authorization, access_token, refresh_token, bearer
You can configure additional fields to exclude via the webhook settings. User-configured exclusions apply in both testing and active modes.
Endpoint Lifecycle
Section titled “Endpoint Lifecycle”Status Flow
Section titled “Status Flow”Webhooks can be in one of three statuses:
| Status | Badge | Behavior |
|---|---|---|
| Testing | Amber | Payloads are stored for preview; no events created |
| Active | Green | Payloads are mapped and written to the events table |
| Disabled | Gray | Endpoint rejects all requests with 404 |
Available transitions:
- Testing → Go Live (active) or Disable
- Active → Pause (disabled) or Test mode (testing)
- Disabled → Enable (active)
Rotation
Section titled “Rotation”Rotating an endpoint creates a new endpoint ID and key while disabling the old one. Use this when a key may have been exposed:
- Click Rotate on the endpoint card
- A new endpoint ID and key are generated
- The old endpoint is immediately disabled
- Update the sending system with the new URL/key
Delete
Section titled “Delete”Deleted endpoints immediately return 404 and cannot receive events.
Rate Limiting
Section titled “Rate Limiting”Each endpoint has a rate limit (default: 120 requests/minute). Exceeding it returns 429 Rate limit exceeded.
Integrating Social Stream Ninja
Section titled “Integrating Social Stream Ninja”Social Stream Ninja aggregates live events from 100+ platforms (YouTube, Twitch, TikTok, etc.) and can forward them to your webhook.
Setup without Custom Headers
Section titled “Setup without Custom Headers”Social Stream Ninja may not support custom HTTP headers. Use api_key mode with the key in the JSON body:
- Create an endpoint with
api_keyauth mode - Copy the generated key
- In Social Stream Ninja, configure the webhook URL:
https://your-domain/api/ingest/webhook/<webhookId>
- Include the key in the JSON payload as the
keyfield
Example Payload
Section titled “Example Payload”{ "platform": "youtube", "username": "alice", "message": "hello from chat", "event_type": "message", "key": "your-api-key-here"}Error Codes
Section titled “Error Codes”| Code | Status | Description |
|---|---|---|
WEBHOOK_NOT_FOUND | 404 | Endpoint does not exist or is disabled/deleted |
WEBHOOK_UNAUTHORIZED | 401 | Key missing or invalid |
WEBHOOK_MAPPING_INVALID | 422 | Mapping produced invalid result (e.g. missing title) |
WEBHOOK_RATE_LIMITED | 429 | Rate limit exceeded |
WEBHOOK_INGEST_FAILED | 500 | Unexpected server error |
Related
Section titled “Related”- Event Stream concept
- Use Case: AI Companion — Context Bro + webhook for browsing context
- Use Case: AI VTuber — Social Stream Ninja + webhook for live chat
- Use Case: Discord Multiverse — multi-agent Discord world