Skip to content

Webhook

Webhook endpoints let external systems send events into your agent’s event stream. Each agent can have multiple endpoints for different integrations.

  1. Open Agent Settings → Webhooks
  2. Enter a name (e.g. youtube-live, discord)
  3. Choose an authentication mode
  4. 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>

When a webhook is in testing mode:

  1. Send a real payload from your external application to the endpoint URL
  2. Open the Configure mapping dialog from the webhook card
  3. Received payloads appear in the Source Payload dropdown (up to 10 most recent)
  4. Use the visual mapping editor to map incoming fields to event properties
  5. Review the live preview to verify your mapping produces correct results
  6. 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.

The mapping dialog provides two modes:

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:
FieldKeyRequiredDefault Template
PlatformplatformNo{{ payload.platform || 'webhook' }}
ElementelementNo{{ payload.username || 'external' }}
Event Typeevent_typeNo{{ payload.event_type || 'message' }}
TitletitleYes{{ payload.message }}
PayloadpayloadNo{{ payload }}

Below the target fields, a live preview shows the resolved values using the currently selected test payload.

Click-to-map workflow:

  1. Click a target field input to focus it
  2. Click a node in the JSON tree on the left
  3. The expression {{ payload.path.to.field }} is automatically inserted
  4. The live preview updates immediately

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.

  • payload refers to the incoming JSON payload
  • payload.path.to.field accesses 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.

ModeSecurityUse Case
openNoneTesting, low-risk internal sources
api_keyKey in header/query/bodyIntegrations that can send a key but not sign
secretKey-based verificationProduction-recommended

For api_key and secret modes, the key can be provided in any of these locations (checked in order):

  1. Authorization: Bearer <key> header
  2. X-Webhook-Key, X-API-Key, or X-Webhook-Secret header
  3. Query parameter: key, api_key, secret, or token
  4. JSON body field: key, api_key, secret, or token

This flexibility allows sources that cannot set custom headers (like Social Stream Ninja) to pass the key in the JSON body or query string.

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.

Webhooks can be in one of three statuses:

StatusBadgeBehavior
TestingAmberPayloads are stored for preview; no events created
ActiveGreenPayloads are mapped and written to the events table
DisabledGrayEndpoint rejects all requests with 404

Available transitions:

  • Testing → Go Live (active) or Disable
  • Active → Pause (disabled) or Test mode (testing)
  • Disabled → Enable (active)

Rotating an endpoint creates a new endpoint ID and key while disabling the old one. Use this when a key may have been exposed:

  1. Click Rotate on the endpoint card
  2. A new endpoint ID and key are generated
  3. The old endpoint is immediately disabled
  4. Update the sending system with the new URL/key

Deleted endpoints immediately return 404 and cannot receive events.

Each endpoint has a rate limit (default: 120 requests/minute). Exceeding it returns 429 Rate limit exceeded.

Social Stream Ninja aggregates live events from 100+ platforms (YouTube, Twitch, TikTok, etc.) and can forward them to your webhook.

Social Stream Ninja may not support custom HTTP headers. Use api_key mode with the key in the JSON body:

  1. Create an endpoint with api_key auth mode
  2. Copy the generated key
  3. In Social Stream Ninja, configure the webhook URL:
    https://your-domain/api/ingest/webhook/<webhookId>
  4. Include the key in the JSON payload as the key field
{
"platform": "youtube",
"username": "alice",
"message": "hello from chat",
"event_type": "message",
"key": "your-api-key-here"
}
CodeStatusDescription
WEBHOOK_NOT_FOUND404Endpoint does not exist or is disabled/deleted
WEBHOOK_UNAUTHORIZED401Key missing or invalid
WEBHOOK_MAPPING_INVALID422Mapping produced invalid result (e.g. missing title)
WEBHOOK_RATE_LIMITED429Rate limit exceeded
WEBHOOK_INGEST_FAILED500Unexpected server error