Skip to main content
Webhooks let you receive outreach engagement events from Topo the instant they occur. When a tracked event happens in your workspace — a contact replies, a hot lead is created, a meeting is booked — Topo sends an HTTP POST to the URL you register, with a signed JSON payload describing the event. A webhook subscription defines which events you want to receive and where to receive them. You can optionally scope a subscription to events from specific sequence templates, keeping your integration focused on the templates that matter. Every delivery is signed with an HMAC-SHA256 signature so you can verify that requests genuinely originate from Topo.
Reading subscriptions requires the webhooks:read scope. Creating, updating, deleting, and testing subscriptions requires the webhooks:write scope.

Subscription status

Event types

Each subscription declares which event types it wants to receive. The type field in every delivered payload is the discriminator.
Topo may add new event types as additive changes within /v1. Your endpoint must accept and ignore unknown type values — do not return a non-2xx status just because you don’t recognise an event type.

Payload families

Topo delivers two payload families. Branch on type before reading fields beyond the shared base.

Sequence-tied events

Most outreach events (message.*, invitation.*, hot_lead.created, meeting.created, sequence.*, task.*) come from sequence activity. They always include sequence_id, sequence_template_id, contact, and sequence_template embeds when the underlying rows exist.

Resource events

contact_entry.resolved, event.resolved, and contact_exclusion.created describe resources that exist outside any sequence run. They use a slimmer base: type, organization_id, contact_id, and contactno sequence_id or sequence_template_id. Deliveries for resource events are sent only to subscriptions whose sequence_template_ids is null (all templates). Subscriptions narrowed to specific templates receive sequence-tied traffic only — see Sequence template scoping.

Webhook payload structure

Every delivery is an HTTP POST with a JSON body. The payload is the same discriminated OutboundWebhookEventPayload object surfaced by the Activities API.
All field names are snake_case.

Embedded summaries

Alongside the raw ids, every sequence-tied payload carries compact copies of the records the event is about. Resource payloads carry contact when a contact is known, plus event-specific ids listed above.
object | null
The person the event is about. Fetch the full record from the Contacts API when you need more than these fields.
object | null
The playbook the sequence is running. Use it to branch on the template a delivery came from without keeping your own id-to-name mapping.
object | null
The email or LinkedIn message the event describes.
object | null
The booked calendar event.
object | null
The manual action item the event describes.
object | null
The hot lead Topo’s AI flagged.
Embeds are a convenience, not the contract — the id fields are. Every embed is nullable, and every field inside one except id is optional. When a referenced row was deleted or cannot be read, Topo still delivers the event with the ids intact and sets the embed to null, so read ids for correlation and treat embeds as best effort.
The Activities API returns the same payload object, embeds included, so a handler written against these fields works whether you stream events or poll for them.

Delivery headers

Every POST Topo sends includes these headers:

Verifying signatures

Every delivery is signed. You should reject requests that fail signature verification to prevent spoofed events from affecting your system. The signature is computed as:
Compare the result (hex-encoded, prefixed with sha256=) against the X-Topo-Signature header. Always compare using a constant-time equality function to prevent timing attacks.
Always verify the signature before acting on a payload. Do not trust the organization_id in the body without first confirming the signature is valid.
Make your endpoint idempotent. In rare cases Topo may deliver the same event more than once (e.g. after a network timeout). Use the activity’s id — available via the Activities API — to deduplicate if needed.

Sequence template scoping

By default a subscription receives events from every sequence template in your workspace. If you want to isolate events from a particular template — for example, routing events from your enterprise outbound template to a different CRM pipeline — set sequence_template_ids when creating or updating the subscription. A subscription with sequence_template_ids receives only events where payload.sequence_template_id is in that list. Resource-family events (no template) are not delivered to narrowed subscriptions — only subscriptions with sequence_template_ids: null receive them. To remove scoping and receive events from all templates again, PATCH the subscription with "sequence_template_ids": null.

Webhook lifecycle

Topo’s API stability policy guarantees the subscription object shape, pagination envelope, and event type discriminator values are frozen within /v1. New event types may be added additively — your integration should ignore unknown type values rather than treating them as errors.