Skip to main content

Read this first

This guide is written for autonomous AI agents operating Puffle on behalf of a human customer. Every customer capability the product exposes through the UI is also exposed through HTTP endpoints documented under API Reference. If you can describe an outcome, there is an endpoint that produces it. If something appears missing from the docs, it is either intentionally out of scope (admin-only tools, inbound webhook receivers) or a gap to report back to the human — do not guess endpoints.

Authentication

Every API call must include a partner API key as a Bearer token:
Authorization: Bearer pk_live_...
  • Keys are created by the human customer via the Puffle dashboard or via POST /api/v1/partners/api-key.
  • Keys are scoped to a single workspace.
  • Never log or echo the key back to the customer.
  • On 401 unauthorized, stop and ask the human for a valid key — do not retry blindly.
See Authentication and Partner API key management.

Boot sequence — the first thing to do

Before issuing any other call, run this two-step boot sequence to discover the workspace state. Skipping it leads to agents operating on incomplete assumptions (wrong ICP, empty context, insufficient credits).
1. GET  /api/onboarding/status    → is the workspace set up?
2. GET  /api/context              → what do I know about this user?

Step 1 — Is the workspace ready?

GET /api/onboarding/status
Returns { onboarding_complete: boolean, ... }. If onboarding_complete: false, stop and escalate to the human — no point launching campaigns, running research, or configuring signals for a user who hasn’t finished setting up their ICP and company profile. The UI blocks those actions too.

Step 2 — What does the workspace know?

GET /api/context
Returns the user’s company profile, positioning, ICP description, target market. Every downstream action that generates content (messages, deep research, lead filters) implicitly uses this context server-side, but you as the agent should still read it:
  • So you can explain the user’s business back to them when asked (“You’re targeting Series A startups in fintech…”)
  • So you can detect a mismatch with the task (if the user asks you to outreach to retail buyers but their ICP is B2B SaaS, flag it)
  • So you can self-select which journey to run (e.g. “prospect reply inbox” is only meaningful if at least one campaign has launched)
After these two calls, branch into the appropriate user journey below.

Credit system — check before spending

Puffle charges credits for actions that call paid third-party services (enrichment, deep research, signal scans, LLM-powered generation). Always preview cost before executing so you can decide whether to proceed or ask the human for approval.
POST /api/credits/preview
Content-Type: application/json

{ "action": "deep_research", "count": 10 }
The response reports credits required and current balance. If balance is insufficient:
  1. Report the shortfall to the human with a specific number.
  2. Do not partially-execute — failed-midway runs are hard to rollback.
  3. Offer to proceed with a smaller batch that fits inside the balance.
See Credit preview.

Async patterns

Expensive operations are async. The pattern is uniform:
  1. POST kicks off the work → responds 202 Accepted with a correlationId (also in the x-correlation-id header) and a reference to a status endpoint.
  2. GET the status endpoint by ID → returns status: "pending" | "running" | "done" | "failed" plus a result payload when done.
  3. Poll with backoff (start 2 s, double up to 30 s). Most operations finish in 30 s–5 min; deep research can take 10–20 min.
Every async response includes the correlationId. If the human reports an issue, capture and pass this ID back — support can trace every downstream call and background job through a single query. Do not busy-loop without backoff. Do not poll more than once per second. Do surface the correlationId to the human in every error message.

Error handling

All errors follow the shape documented in the API Overview:
{ "error": { "code": "invalid_request", "message": "..." } }
StatusAgent response
400 invalid_requestFix the payload from the message content. Do not retry the same body.
401 unauthorizedStop. Ask the human for a valid API key.
403 forbiddenStop. This workspace lacks access to this feature; inform the human.
404 not_foundResource doesn’t exist or belongs to another workspace. Do not retry.
409 conflictResource already exists. Fetch the existing one and continue.
422 unprocessable_entitySemantic error — reread the endpoint doc. Do not retry without changes.
429 rate_limitedBack off. Respect Retry-After if present, otherwise wait 30 s.
500 internal_errorRetry once after 5 s. If it recurs, stop and report the correlationId.

Core user journeys

The five sequences below cover 90% of what a customer-role agent needs to do. Each chains endpoints in a specific order — follow it.

Journey 1 — Launch a campaign end-to-end

1. POST  /api/lists                              → create a list to hold leads
2. POST  /api/leads/search                       → queue a lead search (async, 202)
3. GET   /api/leads/search/:id                   → poll until status=done
4. POST  /api/lists/:id/add-search-results       → attach results to the list
5. POST  /api/campaigns                          → create a campaign shell
6. POST  /api/campaigns/:id/leads                → attach leads from the list
7. POST  /api/campaigns/:id/sequence             → define message sequence
8. POST  /api/email/accounts                     → ensure a sender is attached
9. POST  /api/campaigns/:id/launch               → start sending
10. GET  /api/campaigns/:id                      → poll `status` and `stats`
Related docs: Campaigns · Launch campaign · Lists · Leads search.

Journey 2 — Import leads into a list (CSV / Sales Navigator)

1. POST  /api/lists                                       → create target list
2. POST  /api/lists/:id/import                            → parse CSV/XLSX
3. POST  /api/lists/check-duplicates                      → dedup against existing lists
4. POST  /api/lists/:id/rows                              → insert rows
— or —
1. POST  /api/lists/import-sales-nav                      → queue Sales Nav import (async)
2. GET   /api/leads/search/:id                            → poll for completion
Related: Create list · Import · Sales Nav import.

Journey 3 — Run a deep research report

1. POST  /api/credits/preview   { action: "deep_research" }   → confirm credits
2. POST  /api/v1/research       { topic: "...", inputs: {} }  → 202 + research_id
3. GET   /api/v1/research/:id                                  → poll status
4. GET   /api/v1/research/:id/report                           → fetch final report
Deep research can take 10–20 minutes. Budget accordingly; do not block on sub-minute timeouts. Related: Create research · List research.

Journey 4 — Configure signals and query the feed

1. GET   /api/v1/signals/types                  → list existing signal types
2. POST  /api/v1/signals/types                  → create a custom signal type
3. POST  /api/v1/signals/types/:id/generate     → seed keywords via LLM (async)
4. GET   /api/v1/signals/types/:id              → poll until generation done
5. GET   /api/v1/signals?min_score=70           → read the feed
6. POST  /api/v1/signals/:id/dismiss            → dismiss a signal
7. POST  /api/v1/signals/:id/feedback           → rate signal quality
Signals scan on a schedule. Creating a type does not immediately populate the feed — allow up to 1 hour for the first scan. Related: Signals Overview · Feed · Types.

Journey 5 — Schedule a social post

1. GET   /api/calendar/accounts                 → list connected Late.ai accounts
2. POST  /api/calendar/posts                    → schedule a post (title, body, scheduled_at, account_ids)
3. GET   /api/calendar/posts?from=&to=          → read the calendar
4. POST  /api/calendar/posts/:id/sync-status    → force status refresh
If no Late.ai accounts are connected, direct the human to connect one via the dashboard — connection requires an interactive OAuth flow that agents cannot complete autonomously. Related: Social calendar · Connect Late account.

What agents MUST NOT do

  • Do not call endpoints under /api/admin/* — these are internal team tools, not part of the product surface.
  • Do not call inbound webhook receivers (/api/apify/*, /api/autumn/*, /api/agentmail/*, /*/webhooks) — they are called by external services, never by you.
  • Do not attempt OAuth flows (Unipile, Late, Gmail) autonomously — they require a human-in-the-loop browser session. If a feature requires an OAuth-connected account, tell the human and stop.
  • Do not persist the API key anywhere except in-memory for the duration of the task.
  • Do not exceed 100 requests per minute — see Rate Limits.

Escalation

Stop and ask the human when:
  • Credits are insufficient for the requested work.
  • An operation requires OAuth/browser interaction (account connection, login flows).
  • A 403 forbidden or 404 not_found on a resource you expected to exist.
  • A 500 internal_error that persists after one retry — include the correlationId in the escalation.
  • The requested outcome has no corresponding endpoint documented here.