Skip to main content
GET
/
api
/
activities
List recent workspace activity
curl --request GET \
  --url https://app.puffle.ai/api/activities \
  --header 'Authorization: Bearer <token>'
{ "activities": [ { "id": "aaaa1111-1111-1111-1111-111111111111", "campaign_id": "8c2b2d4e-e29b-41d4-a716-446655440000", "prospect_id": "p1111111-1111-1111-1111-111111111111", "activity_type": "email_replied", "channel": "email", "metadata": { "subject": "Re: Quick question about Acme" }, "created_at": "2026-04-22T14:32:10.231Z", "prospect": { "first_name": "Jane", "last_name": "Doe", "company": "Acme Capital", "linkedin_url": "https://linkedin.com/in/jane-doe" }, "campaign": { "id": "8c2b2d4e-e29b-41d4-a716-446655440000", "name": "Q2 Enterprise Outreach", "type": "email" } } ], "nextCursor": "2026-04-22T14:32:10.231Z|aaaa1111-1111-1111-1111-111111111111" }

Overview

Returns a paginated feed of campaign activity across every campaign the caller owns (or a single campaign via ?campaign_id=). Events include email/LinkedIn sends + replies + bounces, connection accepts, and prospect lifecycle changes. Each entry is denormalized with campaign and prospect identity inlined so a UI can render a feed without N+1 lookups. Pagination uses a composite keyset cursor (<ISO timestamp>|<UUID>) so duplicate created_at values don’t drop rows across pages.

AI agent notes

When to use this. Summarizing “what happened in my workspace since yesterday,” catching up after a long-running background task, or building an activity timeline UI. For per-campaign polling (status, stats), use getCampaign instead — it’s cheaper and structured for that purpose.Pagination protocol.
Page sizeDefault 50, max 200 via ?limit=
Cursor format<ISO timestamp>|<UUID> returned as nextCursor
Last pagenextCursor: null
Malformed cursor400 — do not retry without fixing the cursor
Bare ISO timestamps are also accepted as cursors for backwards compatibility, but prefer the composite form returned by the server.Metadata shape varies by activity_type. Treat metadata as opaque when rendering a generic feed; inspect by type when computing analytics (e.g. email_bounced.bounce_reason, email_sent.subject + message_id).Channel field. channel is one of email, linkedin, or system. system is reserved for engine-level events that don’t tie to a specific send channel.

Authorizations

Authorization
string
header
required

Bearer authentication header of the form Bearer <token>, where <token> is your auth token.

Query Parameters

campaign_id
string<uuid>

Filter to a single campaign. Omit to list activity across every campaign the caller owns.

Pattern: ^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$
limit
integer

Max activities to return per page. Defaults to 50, capped at 200.

Required range: 1 <= x <= 200
cursor
string

Composite keyset cursor of the form <ISO timestamp>|<UUID> returned as nextCursor from the previous page. A bare ISO timestamp is accepted for backwards compatibility. Rejected with 400 if malformed.

Response

A page of activities ordered newest-first. nextCursor is non-null iff more rows are available.

activities
object[]
required
nextCursor
string | null
required

Pass this back as the cursor query param to fetch the next page. null when the current page is the last one.