Skip to main content

Overview

Webhooks enable you to receive real-time notifications when important events occur in Explorium’s data ecosystem. This guide walks you through setting up v2 webhooks to receive push notifications for the business and prospect events you monitor. Unlike v1’s single partner-level webhook, v2 webhooks are first-class, addressable resources:
  • Multiple webhooks — up to 10 per tenant. Creating one never overrides another.
  • Tenant-scoped — resolved from your API key; you never pass a tenant or partner ID.
  • Addressed by webhook_id — server-generated and immutable (e.g. wh_9f2c81ab). Event enrollments bind to it explicitly.
  • Per-webhook secrets — each webhook has its own HMAC secret, rotatable independently.

Quick Start

  1. Register a webhook — create a destination for event deliveries
  2. Implement a secure receiver — validate and process incoming events
  3. Test connectivity — verify the webhook is configured correctly
  4. Enroll for events — subscribe entities, binding each enrollment to a webhook
  5. Process events — receive and handle real-time events as they occur

Step 1: Register Your Webhook

POST /v2/webhooks — only name and webhook_url are required.
Request
Response (201)
Store the webhook_secret now — it verifies event authenticity and is returned only on create and rotate, never on read. Store one secret per webhook_id.

Optional Registration Parameters

Webhook Limits

  • Up to 10 webhooks per tenant; name must be unique within your scope
  • Creating a webhook never overrides an existing one — that v1 behavior survives only on the v1 endpoint
  • Your legacy v1 partner-level webhook appears read-only in List webhooks, flagged legacy: true; v1 enrollments keep delivering to it with no action required

Step 2: Implement Your Webhook Handler

Your webhook handler needs to:
  • Accept HTTP POST requests
  • Validate the signature to ensure event authenticity
  • Process incoming event data based on the event type and enrollment key

Example Implementation (Python with FastAPI)

Python
Security Implementation: The signature is an HMAC over timestamp.payload, computed with the secret of the delivering webhook — the payload’s webhook_id tells you which secret to verify with. This prevents unauthorized systems from sending fake events to your endpoint.

Step 3: Test Webhook Connectivity

POST /v2/webhooks/{webhook_id}/check_connectivity — targeted at one webhook; no request body is needed for a basic check.
Response
The system sends a test event to the webhook and returns the outcome from your handler.

Advanced Testing

Add a simulation block to push realistic mock events — useful for validating your event handling logic end to end:
Request
  • event_name — the event type to simulate
  • number_of_events — how many simulated events to deliver
  • event_time (optional) — the event timestamp to stamp on the simulated events

Step 4: Enroll for Events

Once a webhook is set up, enroll entities for monitoring — every v2 enrollment binds to a webhook explicitly via webhook_id.
Request
Response (201)

Key Enrollment Parameters

  • webhook_id: the delivery destination. The binding is strict — the webhook must exist in your scope and be active. Unknown IDs return 404; a missing webhook_id or wrong scope/status returns 422. Events are never silently delivered elsewhere.
  • enrollment_key: a custom identifier included in every event notification — use it to group enrollments by customer, campaign, or business process and route events accordingly.
  • business_ids / prospect_ids: entities to monitor, up to 1,000 per request. There is no limit on the total enrolled across multiple requests.

Managing enrollments

Each enrollment has a server-generated enrollment_id and a statusactive (delivering) or paused (retained, delivering nothing; set when its webhook is force-deleted). PATCH .../enrollments/{enrollment_id} updates webhook_id, enrollment_key, event_types, or the entity list — re-pointing a paused enrollment to an active webhook reactivates it without re-enrolling entities.

Event Payload Structure

Delivered payloads name their delivery source — webhook_id, tenant_id, partner_id, and enrollment_id — so a shared handler can route without relying on enrollment_key alone:
JSON

Key Fields

webhook_id: the webhook this event was delivered through — also selects the secret for signature verification
enrollment_key: the identifier you provided during enrollment
enrollment_id: the enrollment that triggered this delivery
event_id: a unique identifier for this specific event
event_name: the type of event that was triggered
entity_type: either “business” or “prospect”
data: event-specific data (varies by event type)

Using Webhooks with Claude Code Routines

Claude Code routines can run automatically in response to an external HTTP request through an API trigger. You can point an Explorium webhook directly at a routine’s trigger URL so that every Explorium event fires the routine — and, with the right payload_format, the event data is delivered straight into the routine for processing. No relay or intermediate service is required.

How it works

A routine’s API trigger exposes a fire URL of the form:
This endpoint:
  • Requires an Authorization: Bearer <token> header (generated when you create the routine) and an anthropic-version: 2023-06-01 header.
  • Injects the request body’s text field into the routine as its input, and ignores other top-level fields.
Because the routine only reads a text field, Explorium’s default event object isn’t consumed by the routine on its own. Setting payload_format to stringified_json tells Explorium to deliver the event in a routine-compatible shape:
The text value is the complete Explorium event object serialized as a JSON string, so the routine can parse it and act on the event.

Step 1 — Create the routine

In claude.ai → Code → Routines, create a routine and choose the API trigger (“Trigger from your own code by sending a POST request”). Copy:
  • the trigger’s fire URL, and
  • the token generated for the trigger.
In the routine instructions, tell Claude that each run will receive an Explorium event payload and describe what it should do with it (for example, summarize the event, enrich the entity, or alert a channel).

Step 2 — Register the webhook

Register the routine’s fire URL as a dedicated webhook, supplying the required headers and payload_format: "stringified_json":
Because v2 supports multiple webhooks, the routine can be one of several destinations — keep your CRM sync on its own webhook and bind each enrollment to the right one via webhook_id.
The anthropic-version header is required — without it the routine endpoint rejects the delivery with a 400 error. Each event is delivered as a separate POST, so one routine run is triggered per event.

Step 3 — Test it

Use the connectivity endpoint to push simulated events to your routine:
A "request_status": "success" response means the routine accepted the events. Open the routine’s sessions in claude.ai to see each event rendered and processed.
The token stored in headers can trigger your routine. Treat it as a secret, and rotate it if it may have been exposed.

Managing Your Webhooks

Deleting a webhook that active enrollments reference fails with a conflict unless you pass ?force=true — then the affected enrollments are set to paused (entity lists preserved, IDs returned in affected_enrollment_ids) and can be re-pointed to another webhook later. Enrollments are never silently re-pointed.

Best Practices

  1. One webhook per destination or use case — CRM sync, ops alerts, and automation each get their own webhook, secret, and enrollments.
  2. Use the enrollment_key effectively: structure keys to match your internal systems and use cases.
  3. Validate all signatures: verify every event with the secret of the webhook_id it arrived through.
  4. Set up monitoring: detect delivery failures on your endpoint, and use status: "disabled" to pause a destination without deleting it.
  5. Use proper Content-Type: accept and respond with application/json.

Frequently Asked Questions

Up to 10 per tenant. Each is addressed by its own webhook_id, and creating a new one never overrides an existing one.
The v1 endpoints keep working unchanged, including their register-overrides behavior. Your existing partner-level webhook appears read-only in GET /v2/webhooks flagged legacy: true, and v1 enrollments keep delivering to it with zero action required.
POST /v2/webhooks/{webhook_id}/rotate_secret — it returns a new secret for that webhook only. In v1 you had to re-register; in v2 rotation never touches other webhooks.
Each enrollment request is limited to 1,000 IDs, but there’s no limit on the total enrolled across multiple requests.
The delete fails with a conflict unless you pass ?force=true. Forced deletion pauses the affected enrollments — delivery stops, entity lists are preserved — and you can re-point them to another webhook via PATCH without re-enrolling.
Two levers: separate webhooks per destination, and the enrollment_key on each enrollment. Both arrive in every event payload, alongside webhook_id and enrollment_id.
Yes. Register a dedicated webhook pointing at the routine’s API-trigger fire URL, pass the routine’s Authorization and anthropic-version: 2023-06-01 headers via headers, and set payload_format to stringified_json. See Using Webhooks with Claude Code Routines.