IntegrationsWebhooks

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:

  1. In the Bullseye dashboard, open Automations
  2. Create an automation from the Forward to a custom webhook on visitor identified template
  3. Fill in:
FieldRequiredNotes
Webhook URLYesYour HTTPS endpoint
HTTP methodNoDefaults to POST
Bearer tokenNoSent as Authorization: Bearer <token>
Extra headersNoJSON object, e.g. {"X-Custom": "value"}
  1. 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_revealed is 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": { ... }
}
FieldDescription
eventReserved. Currently not populated reliably. Read the event type from payload.event_type instead
payloadThe 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 2xx quickly and process asynchronously
  • Deduplicate on payload.session_id in case you replay or re-run events

Best Practices

  • Use HTTPS and a Bearer token or secret header
  • Respond fast: return 200 immediately, queue the work
  • Key on payload.event_type, not the top-level event
  • Treat "" as missing for text fields
  • Log failures and watch the automation’s run history