payload that describes exactly what happened — which contact it involved, which sequence it came from, what channel was used, and any event-specific metadata. The payload schema is the same discriminated union that Topo delivers to webhook subscribers, so you can build consistent pipelines whether you are polling or streaming.
Activities are ideal for building custom reporting dashboards, syncing engagement history to a CRM, or auditing outreach behaviour without setting up a webhook endpoint.
All Activities endpoints require an API key with the
activities:read scope.The activity object
An activity represents a single discrete event in the lifecycle of an outreach sequence. Thepayload.type field is the discriminator — it tells you which event occurred and determines which additional fields are present on the payload.
Activity fields
Unique identifier for this activity record.
Timestamp at which the activity was recorded, in UTC with timezone offset.
Discriminated event payload. The shape varies by
payload.type; see Event types below.Event types
Thepayload.type field is always one of the following values. Topo may add new event types as additive changes within /v1; your code should handle unknown values gracefully rather than treating them as errors.
type value | What it means |
|---|---|
message.sent | An email or LinkedIn message was sent to the contact. |
message.opened | The contact opened an email. |
message.link_clicked | The contact clicked a tracked link in an email. |
message.replied | The contact replied to a message. Includes a metadata.reply_category field (filled asynchronously — may be null immediately after delivery). |
invitation.sent | A LinkedIn connection request was sent. Includes metadata.step_number. |
invitation.accepted | The contact accepted a LinkedIn connection request. |
hot_lead.created | Topo’s AI flagged the contact as a hot lead. |
meeting.created | A meeting was booked with the contact. |
sequence.created | A contact was enrolled into a sequence. |
sequence.paused | The sequence was paused. May include metadata.paused_until and metadata.last_step_executed. |
sequence.resumed | A paused sequence was resumed. |
sequence.stopped | The sequence was stopped early. Includes metadata.stopped_reason and metadata.error_code. |
sequence.completed | The sequence ran to completion. |
task.created | A manual task was created for the contact. |
task.completed | A manual task was marked complete. |
task.skipped | A manual task was skipped. |
List activities
created_at descending by default. Use the filter parameters to narrow results.
Query parameters
Return only activities for a specific contact.
Return only activities from a specific sequence run (enrollment).
Return only activities from sequences based on a specific template.
Filter by the type of resource involved. One of
MESSAGE, INVITATION, HOT_LEAD, MEETING, SEQUENCE_STEP, SEQUENCE, TASK.Filter by outreach channel. One of
EMAIL, LINKEDIN, MANUAL.Filter by the low-level event type. One of
SENT, REPLIED, OPENED, LINK_CLICKED, ACCEPTED, CREATED, PAUSED, RESUMED, STOPPED, COMPLETED, SKIPPED.Return activities strictly after this timestamp (exclusive). Useful for incremental polling — store the
created_at of the most recent activity you processed and pass it here on the next request.Return activities strictly before this timestamp (exclusive).
Field to sort by. Currently only
created_at is supported.Sort direction.
ASC or DESC.Page number to retrieve. Must be ≥ 1.
Number of items per page. Must be between 1 and 100.
Response
Returns a pagination envelope containing a list of activity objects.Array of activity objects for the current page.
Total number of activities matching the current filters.
Total number of pages given the current
size.Whether there are more pages beyond the current one.
Example — list replies and hot leads for a contact
Get a single activity
Path parameters
The unique identifier of the activity to retrieve.
Example
Polling for new activities
The Activities API is well-suited to incremental polling patterns for CRM sync or custom reporting. A reliable approach:- On first run, fetch activities with
sort_order=ASCand store thecreated_atof the last item in your cursor. - On subsequent runs, pass that cursor as
created_at_afterto retrieve only new events. - Page through results using
has_moreuntil it isfalse.
The pagination envelope shape —
{ items, total_count, total_pages, has_more } — is frozen by Topo’s API stability policy. New response fields may be added additively; your client should ignore unknown fields.