Skip to main content
GET
/
api
/
campaigns
/
{id}
/
validate
Validate campaign readiness before launch
curl --request GET \
  --url https://app.puffle.ai/api/campaigns/{id}/validate \
  --header 'Authorization: Bearer <token>'
{
  "ready": true,
  "checks": {
    "is_draft": true,
    "has_sender_accounts": true,
    "sender_accounts_ready": true,
    "has_prospects": true,
    "prospect_count": 120,
    "has_sendable_nodes": true,
    "all_nodes_have_content": true,
    "messages_generated": true,
    "message_count": 120
  },
  "errors": [],
  "warnings": []
}

Overview

A comprehensive readiness check that an agent should always run before POST /api/campaigns/{id}/launch. Returns a structured { ready, checks, errors, warnings } payload covering eight dimensions:
  • Campaign is in draft status
  • At least one sender account is attached, and every sender is in a ready state (active/warming for email, connected for LinkedIn)
  • At least one pending prospect exists
  • The sequence contains at least one sendable node for the channel
  • Every non-AI sendable node has subject + body content
  • Draft messages are present in campaign_prospect_messages
  • AI nodes have pre-generated examples (warning-only)
If the campaign isn’t a draft, the response short-circuits — the other checks are skipped and only the Campaign is <status> — must be draft to launch error is returned.

AI agent notes

Launch blockers vs. advisories. errors blocks launch; warnings does not. Both should be surfaced to the user verbatim.Messages-generated is a warning, not an error. Missing draft messages are a warning when non-AI sendable nodes exist (messages can still be generated at launch), and silently skipped when the only sendable nodes are AI. Agents shouldn’t gate on messages_generated === true.No side effects. Safe to call as often as you like. Call it right before launchCampaign — status changes between these two calls are the only race, and they surface as a 400 on launch.Repair loop. If ready === false, walk errors top-to-bottom: fix draft status via updateCampaign, add senders via POST /api/campaigns/{id}/senders, add prospects via POST /api/campaigns/{id}/leads, fill sequence content via updateCampaign, optionally call POST /api/campaigns/{id}/generate-messages with action: "resolve". Re-validate after each fix.

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

Validation snapshot. ready tells you whether launch would succeed right now.

Full pre-launch validation snapshot. Surface errors to the user verbatim before calling launchCampaign.

ready
boolean
required

True iff errors is empty. Warnings alone do not block launch.

checks
object
required

Individual readiness signals. A campaign is launch-ready when every *_ready / has_* flag is true AND errors is empty.

errors
string[]
required

Human-readable blockers. Each string is a specific, actionable reason the campaign cannot launch yet.

warnings
string[]
required

Non-blocking advisories — e.g. AI nodes without pre-generated examples (messages get generated at launch).