Skip to main content
GET
/
api
/
dashboard
/
analytics
Aggregate weekly + all-time campaign stats
curl --request GET \
  --url https://app.puffle.ai/api/dashboard/analytics \
  --header 'Authorization: Bearer <token>'
{ "weekly": [ { "week_start": "2026-04-06", "linkedin": { "connection_sent": 40, "connected": 12, "message_sent": 6, "replied": 1 }, "email": { "sent": 80, "replied": 3, "bounced": 1 } }, { "week_start": "2026-04-13", "linkedin": { "connection_sent": 35, "connected": 18, "message_sent": 10, "replied": 2 }, "email": { "sent": 120, "replied": 7, "bounced": 2 } }, { "week_start": "2026-04-20", "linkedin": { "connection_sent": 10, "connected": 4, "replied": 0 }, "email": { "sent": 60, "replied": 5, "bounced": 0 } } ], "allTime": { "linkedin": { "connection_sent": 410, "connected": 192, "message_sent": 88, "replied": 14 }, "email": { "sent": 980, "replied": 42, "bounced": 6 } }, "campaigns": [ { "id": "8c2b2d4e-e29b-41d4-a716-446655440000", "name": "Q2 Enterprise Outreach", "type": "email", "status": "active" }, { "id": "aaaa1111-1111-1111-1111-111111111111", "name": "Founder Q2 Connects", "type": "linkedin", "status": "active" } ] }

Overview

Returns two views of campaign activity across every campaign the caller owns (or a filtered subset via ?campaign_ids=):
  • weekly — chronological list of per-week deltas, split by linkedin / email. Derived from campaign_weekly_stats snapshots (each snapshot is cumulative; delta is the difference from the previous snapshot, summed across campaigns). The first snapshot per campaign is treated as a baseline and excluded from the series.
  • allTime — cumulative counters summed across every campaign in the query. Read directly from campaigns.stats so it always reflects the latest engine writes, not a snapshot.
Also returns a campaigns array of identity tuples (id, name, type, status) for every campaign included in the rollup.

Query parameters

  • campaign_ids — comma-separated UUIDs to restrict the rollup. Omit for all campaigns the caller owns.
  • rangeall / 12w / 26w / 52w. Trims the weekly series to a trailing window. Defaults to all. Invalid values silently fall back to all.

AI agent notes

This is the endpoint behind the primary dashboard. Good for summarizing “what’s happened across my workspace” or plotting weekly trends. For per-campaign polling during a launch, use getCampaign — it’s cheaper and has status + stats directly.Weekly series needs at least two snapshots per campaign to show anything. Before the second weekly snapshot (captured Monday by the snapshot-weekly-stats cron), a campaign contributes only to allTime. This is why freshly-launched campaigns show allTime totals but empty weekly buckets — that’s expected, not a bug.Empty stats buckets aren’t errors. weekly: [] with allTime.linkedin: {} and allTime.email: {} means the caller has no campaigns yet.No LLM or external calls. Pure database read — safe to hit at normal UI refresh cadences (e.g. every 30–60 s on an open dashboard).

Authorizations

Authorization
string
header
required

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

Query Parameters

campaign_ids
string

Comma-separated campaign UUIDs to restrict the rollup to a subset. Omit to aggregate across every campaign the caller owns.

range
enum<string>

Trailing window for the weekly series. Defaults to all when omitted or invalid.

Available options:
all,
12w,
26w,
52w

Response

Rollup for the requested campaigns and range. Empty weekly and empty buckets are not errors — they just mean the caller has no campaigns or no deltas yet.

Analytics payload ready to feed a dashboard — no post-processing needed by the caller.

weekly
object[]
required

Chronological list of weekly deltas (oldest → newest). Empty when the caller has no campaigns.

allTime
object
required

Cumulative totals summed across every campaign in the query — pulled directly from campaigns.stats at read time, so it always reflects the latest engine writes (not a weekly snapshot).

campaigns
object[]
required

Identity tuples for the campaigns included in this rollup. Empty when the caller has no campaigns.