Webhooks
Send every identified visitor to your own endpoint. Bullseye POSTs JSON with the visitor, company, session, and page views, so you can feed internal tools, custom CRMs, or anything that accepts HTTP callbacks.
Plan Requirement
Custom webhook automations are included on every plan. Partner identification webhooks (whitelabel embed) are Enterprise only and use a different setup. See Partner API webhooks.
Setup
Webhooks are set up as an automation:
- In the Bullseye dashboard, open Automations
- Create an automation from the Forward to a custom webhook on visitor identified template
- Fill in:
| Field | Required | Notes |
|---|---|---|
| Webhook URL | Yes | Your HTTPS endpoint |
| HTTP method | No | Defaults to POST |
| Bearer token | No | Sent as Authorization: Bearer <token> |
| Extra headers | No | JSON object, e.g. {"X-Custom": "value"} |
- Save and turn the automation on
Use the automation’s test action to send a sample event before going live. Test events carry "test_event": true and a reduced set of sample fields.
When it fires
- Once per visitor session, the first time that session is identified
- Not on later identifications in the same session
- Not on phone reveals.
visitor.phone_revealedis delivered to Partner API webhooks only
Request
POST <your webhook URL>
Content-Type: application/json
Authorization: Bearer <token> (only if you set one)
<your extra headers>The body wraps the identification payload:
{
"event": "",
"payload": { ... }
}| Field | Description |
|---|---|
event | Reserved. Currently not populated reliably. Read the event type from payload.event_type instead |
payload | The full identification payload (snake_case). Every field is documented in API reference: Webhooks |
Example body
Trimmed for length. See the full payload example for every field.
{
"event": "",
"payload": {
"event_type": "visitor.identified",
"timestamp": "2025-01-15T10:30:00Z",
"organization_id": "550e8400-e29b-41d4-a716-446655440000",
"session_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"workspace": "Acme Corp",
"visitor": {
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"email": "jane.smith@acme.com",
"first_name": "Jane",
"last_name": "Smith",
"job_title": "VP of Marketing",
"phone": "",
"icp": true,
"icp_statuses": { "enterprise-saas": true },
"persona_match": true
},
"company": {
"name": "Acme Corp",
"domain": "acme.com",
"employee_size_range": "101-500"
},
"session": {
"landing_page": "https://acme.com/pricing",
"country": "US",
"region": "Florida",
"city": "Boynton Beach",
"isp": "AT&T Enterprises, LLC",
"asn": "AS7018",
"connection_type": "isp",
"is_hosting": false,
"is_anonymous": false,
"tracking_params": { "gclid": "abc123" }
},
"page_views": [
{ "url": "https://acme.com/pricing", "visited_at": "2025-01-15T10:25:00Z" }
]
}
}Missing text fields arrive as empty strings (""), not null. Only visitor.homeowner, visitor.married, and visitor.children can be null.
The same session IP fields are returned on the visitor profile API as SessionProfile (camelCase: isp, asn, connectionType, isHosting, isAnonymous). See IP intelligence.
Securing your endpoint
Custom webhook automations are not signed. There is no X-Bullseye-Signature header on this path. To authenticate requests:
- Set a Bearer token and reject requests without it
- Or add a shared secret in Extra headers (e.g.
{"X-Webhook-Secret": "..."}) and check it - Use HTTPS only
HMAC-SHA256 signatures are available on Partner API webhooks.
Delivery
- Each event is sent once. There are no automatic retries
- If your endpoint is down or errors, that event is not resent. Check the automation’s run history for failures
- Respond with a
2xxquickly and process asynchronously - Deduplicate on
payload.session_idin case you replay or re-run events
Best Practices
- Use HTTPS and a Bearer token or secret header
- Respond fast: return
200immediately, queue the work - Key on
payload.event_type, not the top-levelevent - Treat
""as missing for text fields - Log failures and watch the automation’s run history