Skip to main content
GET
/
api
/
campaigns
/
{id}
Get a campaign
curl --request GET \
  --url https://app.puffle.ai/api/campaigns/{id} \
  --header 'Authorization: Bearer <token>'
{
  "campaign": {
    "id": "8c2b2d4e-e29b-41d4-a716-446655440000",
    "user_id": "11111111-1111-1111-1111-111111111111",
    "type": "email",
    "name": "Q2 Enterprise Outreach",
    "status": "active",
    "daily_limit": 50,
    "stop_on_reply": true,
    "open_tracking": true,
    "signature": "Best,\n%first_name%",
    "skip_other_campaigns": null,
    "operating_hours": null,
    "stats": {
      "total": 120,
      "sent": 34,
      "replied": 4,
      "bounced": 1,
      "completed": 0,
      "timed_out": 0
    },
    "created_at": "2026-04-18T15:12:00Z",
    "updated_at": "2026-04-21T09:00:00Z",
    "sender_accounts": [
      {
        "id": "aaaa1111-1111-1111-1111-111111111111",
        "type": "email",
        "email_address": "[email protected]",
        "provider_account_id": null,
        "display_name": "Sarah",
        "first_name": "Sarah",
        "last_name": null,
        "status": "active",
        "daily_limit": 50,
        "weekly_connection_limit": null,
        "weekly_message_limit": null,
        "is_premium": null
      }
    ]
  },
  "sequence_nodes": [
    {
      "id": "bbbb1111-1111-1111-1111-111111111111",
      "campaign_id": "8c2b2d4e-e29b-41d4-a716-446655440000",
      "position": 0,
      "type": "email",
      "subject": "Quick question about {{company}}",
      "body": "Hi {{first_name}}, ..."
    },
    {
      "id": "bbbb2222-1111-1111-1111-111111111111",
      "campaign_id": "8c2b2d4e-e29b-41d4-a716-446655440000",
      "position": 1,
      "type": "end"
    }
  ],
  "prospects_by_status": {
    "pending": 82,
    "sent": 34,
    "replied": 4
  },
  "prospects_by_node": {
    "__none__": {
      "replied": 4,
      "completed": 0
    },
    "bbbb1111-1111-1111-1111-111111111111": {
      "pending": 82,
      "sent": 34
    }
  }
}

Overview

Returns the canonical campaign entity plus two aggregate views of its prospects:
  • prospects_by_status — a simple count-by-status map, ideal for progress bars (sent: 34 / total: 120)
  • prospects_by_node — a two-level nodeId → status → count map, useful for pipeline visualization (which step is holding up the cohort)
This is the endpoint you poll after launchCampaign. status and stats.sent are the fields that actually move — everything else is mostly static once the campaign is launched.

AI agent notes

Polling cadence after launch:
Campaign stateCadence
launchingevery 30 s until it flips to active (typically ≤ 2 min)
active with stats.sent < stats.totalevery 1–5 min
pausedstop polling; wait for user action
completedstop polling
Terminal signals — stop polling when you see any of:
  • status === "completed"
  • stats.completed + stats.replied + stats.bounced + stats.timed_out >= stats.total
  • status === "paused" and the user hasn’t asked to resume
No side effects. Safe to call as often as needed — but respect the 100 req/min rate limit on the API overall, and don’t hammer this endpoint when other work is queued.

Authorizations

Authorization
string
header
required

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

Path Parameters

id
string<uuid>
required

Campaign UUID

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)$

Response

Campaign detail with sequence and prospect aggregates.

campaign
object
required

Canonical campaign entity.

sequence_nodes
object[]
required
prospects_by_status
object
required

Map of prospect status → count, e.g. { "pending": 42, "sent": 34, "replied": 2 }. Use this for progress bars and pipeline summaries.

prospects_by_node
object
required

Two-level map: nodeId → status → count. The key __none__ holds prospects with no current node (not yet started or terminal).