Create draft campaigns and manage their lifecycle with advanced sequencing
The Campaigns API lets connected tools create draft campaigns, add leads, list and inspect lifecycle state, pause or end campaigns, use Fast Forward on nearly complete campaigns, and reopen ended campaigns using your Organization API Key.
Create a draft campaign with leads, sending schedule, and automated email sequence steps.
Add leads to an existing campaign while applying the same dedupe and validation rules.
List by exact status or lifecycle scope, inspect available actions, pause or end campaigns, use Fast Forward on nearly complete campaigns, and reopen ended campaigns.
All requests use the standard bearer token header.
http:// or https:// and contain linkedin.com._ or - only, up to 100 characters. Reserved keys include id, customer_id, email, first_name, last_name, company, company_name, linkedin_url, timezone, created_at, and updated_at.lead_dedupe_scope must be none, active_campaigns, all_campaigns, or all_audiences. Omitted or empty values default to none.YYYY-MM-DD value when a valid campaign timezone is included in the schedule. Responses keep completion_deadline as date-only for compatibility and expose the exact stored cut-off in completion_deadline_at.Use GET /api/v1/campaigns/{campaign_id}/activation-readiness to see the current Ready state and each blocking action for a campaign in the API key's workspace. The /sequences and /sequences/reorderability reads return saved steps and whether they may be reordered. The /mailbox-allocation-policy read returns only the customer-visible overlap_allowed flag; detailed routing controls remain staff-only. Use PUT /api/v1/campaigns/{campaign_id}/schedule with an IANA time_zone and a sending_schedule map such as {"Mon":{"start_time":"09:00","end_time":"17:00"}}. An empty map clears the sending windows. Readiness is recalculated from current campaign data after a change.
POST /api/v1/campaigns/{campaign_id}/duplicate copies reusable content into a new unsent draft. Mailboxes and routing are not copied unless you explicitly choose reviewed infrastructure sharing. DELETE /api/v1/campaigns/{campaign_id}?confirm=true soft-deletes a campaign after it has stopped sending, and POST /api/v1/campaigns/{campaign_id}/restore restores a deleted campaign subject to name and domain ownership checks. POST /api/v1/campaigns/{campaign_id}/test-email sends from an active physical mailbox assigned to this campaign and workspace to the specified test addresses only when the request includes confirm_send: true. It accepts at most 50 addresses and 100 total messages per request; variant_label requires step_number. It supports the same creative snapshot fields as the browser's test-send action. The campaign's click-tracking choice also applies to test emails: tracking On rewrites eligible links on the selected mailbox's sending domain and requires fresh readiness; tracking Off retains ordinary original links and resolves existing Beam redirect links to their final destinations so copied lead claims cannot collect test engagement. Test-link clicks do not enter campaign lead analytics. An unavailable tracking domain is reported in the per-email failed results without sending an untracked fallback.
If mail maintenance interrupts a test batch after any message was accepted, the response is HTTP 200 with code: sending_maintenance_partial, retryable: false, and explicit sent and deferred lists. Never replay the full batch. Retry each recipient in one request using retry.messages with the deferred to, step and variant values, and retry.sent with that recipient's accepted receipts (including message_id and subject). Accepted parents provide threading context and are not resent; deferred steps run in order. HTTP 503 with code: sending_maintenance and Retry-After: 15 is used only when no message was accepted.
All workspace users and workspace-scoped API keys can deliberately share eligible sending infrastructure between campaigns in that workspace. Sharing starts off. Spam complaints from one campaign can affect the reputation of other campaigns using the same domain, even with different mailboxes. Sharing a physical mailbox also shares its send limits, cooldown and pacing; concurrent campaigns, including the original, may send more slowly. Sharing adds no capacity and does not launch or resume sending. See the manual for manual sequential sending.
First call GET /api/v1/campaigns/{campaign_id}/mailboxes/sharing-preview. Review the named owners, eligible mailboxes, warnings, and review_fingerprint. For creation, read this on the source campaign; for assignment, read it on the destination campaign. Pass that exact value as infrastructure_sharing_review_fingerprint with acknowledge_shared_infrastructure_risks: true and the explicit sharing flag on the write. If ownership or availability changes, the write rejects the old review; refresh and review again.
POST /api/v1/campaigns/{campaign_id}/duplicate: provide name and share_infrastructure: true to create a new draft with eligible source mailboxes and routing. Omitting sharing preserves the existing unsent draft behavior without infrastructure.POST /api/v1/campaigns/{campaign_id}/leads/move/preview and /leads/move: review the selected campaign leads, then move them. Provide new_campaign_name and new_campaign_type for a new cloned or blank destination, plus share_infrastructure: true to share with the source. Moving to an existing target_campaign_id does not change its infrastructure. A move removes the leads from the source.POST /api/v1/campaigns/{campaign_id}/leads/follow-up/preview and /leads/follow-up: review eligibility, then provide new_campaign_name and the lead selection. Set share_infrastructure: true to reuse eligible source infrastructure. Follow-up retains the source leads and creates a new draft.POST /api/v1/campaigns/{campaign_id}/mailboxes/assign: provide the complete active mailboxes list with mailbox_id and mailbox_address. Omitted existing assignments are removed; an empty list removes all assignments subject to continuity checks. To use occupied infrastructure, add allow_shared_infrastructure: true with the current sharing review and risk acknowledgement.GET /api/v1/campaigns/{campaign_id}/boxhost-routing and GET /api/v1/campaigns/{campaign_id}/boxhost-routing/targets/{target}/senders return routing and sending-pool mailbox candidates. POST on the latter path adds reviewed mailbox choices using expected_revision, pool_mode, and at least one new mailboxes entry. Include campaign_mailbox_assignment_ids to retain current dedicated-pool memberships. Occupied infrastructure requires the same explicit allow_shared_infrastructure, review fingerprint and acknowledgement. Boxhost target keys are google_workspace, microsoft_365, seg, and default.Sharing mutation requests are limited to 1 MiB of JSON. These operations keep mailbox lifecycle, health, ownership and continuity validation. A sharing choice does not override those checks or grant access to another workspace. Duplication can trigger configured campaign-created workspace webhooks after commit. Lead move and follow-up actions schedule contact-analysis jobs after commit. If a creation response is lost, inspect the campaign list before retrying; retrying can create another draft.
Begin with GET /api/v1/campaigns/{campaign_id}/creative. It returns target-labelled Default and adaptation documents plus the server-owned adaptations_activated capability; the capability is not a client request flag or response filter. Use the Creative endpoints to save one or more numbered subjects above each shared body, plus planned subject eligibility, variants, step delays, and threading settings before approval. Updating Creative saves immutable snapshot history but does not change the Ready Creative used for future sends.
Creative update requests accept a JSON body of up to 1 MiB (1,048,576 bytes), counting escaping and whitespace inside the JSON value. Larger requests return HTTP 413 with a message asking you to shorten the copy and try again. API clients can also send fewer documents in one request. A Creative update accepts at most 140,400 documents (50 steps, 26 variants, 26 subjects plus one body, across four targets) and 50 step settings. These are per-request limits, not a total size limit for a campaign. REST generated-draft apply retains its existing 64 KiB JSON limit and HTTP 400 error for an unreadable or oversized draft.
Template audits block launch and resume when Creative exceeds 1,000 distinct template variables, 10,000 template variable uses, 20,000 fallback alternatives across distinct template variables, or 2 MiB of template variable text repeated across its uses. These budgets count matching template variable text at the same position once across boxhost targets; an edited adaptation that shifts positions counts as new uses. The audit returns one blocking invalid_syntax issue with syntax_kind: audit_limit_exceeded, naming the limit and a field where it was crossed. Shorten or remove the indicated template content, then mark Creative Ready again. A partial audit does not permit sending to start. Mark Ready does not run these budgets; a campaign can pass Mark Ready and then be blocked by the launch audit.
Draft subjects and bodies larger than 64 KiB can still be saved within the request limit. Mark Ready rejects active fields larger than 65,536 raw UTF-8 bytes; shorten the named Step, Variant, and field before marking Creative Ready. Campaign submit retains its stricter existing limits: subjects up to 200 bytes and bodies up to 10,000 characters.
Assess draft copy before saving with POST /api/v1/creative/quality/assess. Submit a subject and body string, using an empty subject for a threaded step. The response contains the Creative editor's six advisory metrics, their guidance and descriptions, and text findings with UTF-16 offsets. RANDOM options use expected word counts and the worst option's spam-trigger score; findings still identify each matching option. Each field is limited to 64 KiB, the complete JSON request to 769 KiB including escaping and whitespace, template nesting to 32 levels, total RANDOM alternatives to 1024, and the result to 256 findings. Oversized or overly dense copy is rejected instead of returning a partial assessment. This read-only call does not save, approve, or send Creative.
Whole-step pause state is returned as paused_step_numbers in Creative reads and is_step_paused on sequences. Mark Creative Ready keeps each paused step at its number when Default body document IDs match or body copy is byte-identical for the same variants. Moving or replacing paused copy requires resuming the step or undoing the change first. A deleted tail loses its pause only after unsettled sends clear, with an attributed Activity event. Step numbers outside 1–50 return 400; a missing configured step returns 404; state conflicts return 409.
Call POST /api/v1/campaigns/{campaign_id}/creative/approve when the current Creative working copy should become an immutable approved snapshot and be marked Ready for future sends. Existing Creative fields are protected from accidental overwrite unless overwrite_existing is true. New subject numbers must leave each body with a contiguous set starting at 1; one request may provide a complete batch in any array order. Optional is_disabled on subject documents plans eligibility for the next Ready Creative. Use PATCH /api/v1/campaigns/{campaign_id}/subjects/{subject_id} to change one current Ready subject without editing or reapproving the shared body.
POST /api/v1/campaigns/{campaign_id}/creative/preview renders a templates object (use body for the email body) with optional data and pick_first. It reads current campaign tracking: On returns working anonymous redirect URLs; Off keeps ordinary original links and resolves existing Beam redirects to their final destinations, without allocating links or requiring redirect readiness. The response contains rendered, audit, tracking_enabled, and the selected sending_domain. An optional owned sending_domain selects the host; otherwise an assigned domain is preferred, then an existing ready workspace domain. Unavailable tracking returns 409 with retry guidance. Identical domain/destination pairs reuse immutable anonymous mappings. No Creative, approval, lead, send or engagement identity is created. These links are previews, not an individual lead's authorized send. Use preserve_templates: true for Ready display to retain the approved template text and change only its eligible URL representation. Requests are limited to 256 KiB and 1 to 51 templates totaling at most 128 KiB. Regenerated RANDOM choices return an optional render_seed; this only replays rendering choices and authorizes no send. A text-only preview needs no ready redirect host.
To test the selected current draft, provide the body and subject document IDs with their current version numbers, step, variant and adaptation target. This works before Mark Creative Ready and does not replace the approved snapshot. A threaded draft test sends its current parent draft first. Optional preview_rendering: {"pick_first": true} selects the first RANDOM choices; use {"pick_first": false, "seed": render_seed} to replay a regenerated preview. Optional variables.email, sender_first_name and sender_last_name preserve preview personalization. Omit these additive fields to retain existing test-recipient substitution and rendering. Stale versions return 409 before sending.
GET /api/v1/campaigns/{campaign_id}/creative/generation-capability returns the current workspace_revision, model, source limits, and remaining quota. Generate a transient draft with POST /api/v1/campaigns/{campaign_id}/creative/generations. Provide a fresh UUID operation_id, mode: "initial" or "regenerate", the current base_revision, audience, offer, and exactly one of source_text or source_pdf_base64. Regeneration also requires the current draft, target_step, and target_field. Text is limited to 14 KiB; decoded PDFs are limited to 20 MiB. Generation uses the same included workspace and campaign quota as the Creative editor. A completed operation ID cannot replay its transient result, so retain the returned draft until you apply or discard it.
POST /api/v1/campaigns/{campaign_id}/creative/generated-draft/apply takes generation_request_id, base_revision, and the returned draft. It replaces the editable working copy only if Creative has not changed, and creates a recovery snapshot. It does not mark Creative Ready or send email. GET /api/v1/campaigns/{campaign_id}/creative/workspace returns documents, step settings, checkpoints, comment threads, and the current revision. POST /api/v1/campaigns/{campaign_id}/creative/checkpoints creates a labelled checkpoint for the current documents; POST .../checkpoints/{checkpoint_id}/restore restores one document using expected_revision. GET /api/v1/campaigns/{campaign_id}/creative/workspace-snapshots lists the three most recent retained recovery snapshots; POST /api/v1/campaigns/{campaign_id}/creative/workspace-snapshots/{snapshot_id}/restore requires expected_revision and creates a pre-restore snapshot.
Collaborate through POST /api/v1/campaigns/{campaign_id}/creative/comments with creative_document_id and body, optionally adding an anchor range and selected text. Use POST .../comments/{thread_id}/replies with body, POST .../comments/{thread_id}/resolve and .../reopen, or DELETE .../comments/{thread_id} to soft-delete a thread. API and MCP comments display an explicit agent author name. Real-time browser editing sessions and cursor locks remain part of the signed-in UI collaboration protocol.
Use POST /api/v1/campaigns/{campaign_id}/leads/from-audience/preview with {"audience_id":"..."} to inspect active audience members, dedupe conflicts, blocklist matches, and send eligibility. Apply with POST /api/v1/campaigns/{campaign_id}/leads/from-audience and the same audience ID. Preview and apply return a lifecycle conflict when the campaign no longer accepts leads. Requests are limited to 64 KiB. Audiences above 100,000 active leads are rejected by preview and apply without importing a partial audience. The campaign and audience must belong to the API key's workspace. To change the campaign's dedupe policy, pass the same leadDedupeScope in both preview and apply; omit it from both to keep the current policy.
Submit the complete campaign or add-leads request with preview_only: true. The response names other affected campaigns and compares current and imported values. When confirmation_required is true, obtain an explicit choice, then resend the unchanged request with preview_only: false, review_token from review.token, and decision: "overwrite" or "preserve". A stale review must be reviewed again. Current-campaign-only and finished-only changes do not require an extra decision.
Successful apply responses can contain failed rows. Inspect row_outcomes for every input row: conflicting identities are left unapplied while independently valid rows proceed. Do not retry successful rows. Blank imported values do not erase existing details, and choosing overwrite never merges different people. The user manual explains shared values and finished campaigns.
Use an Organization API Key to list and filter campaign leads with GET /api/v1/campaigns/{campaign_id}/leads. The response includes page, page size, total count, status counts, and each lead's current campaign state. GET /leads/removal-reasons returns active reason codes and text requirements. All routes require access to the campaign's workspace.
For a bulk removal, send the same scope (selected or filtered), lead IDs or filters, and exclusions to POST /leads/remove/preview, inspect the removable count, then call POST /leads/remove with an active reason_code and confirm_removal: true. The preview is read-only and does not reserve the selection; review again if the campaign changes. POST /leads/{campaign_lead_id}/remove removes one lead with a reason and the same explicit confirmation. Removed membership and history cannot be restored by these routes.
PATCH /leads/{campaign_lead_id}/personalization updates allowed identity and custom-attribute fields through the same validation as the browser. Successful edits record the API key actor and changed field categories in the journal, without copying field values into the audit entry. POST /leads/top-up-from-csv accepts a multipart CSV file and optional column mappings, review token, and preserve/overwrite decision. Use preview_only=true first; an apply that changes shared lead values may require the returned review token and explicit decision. The public multipart request is limited to 10 MiB. Inspect row outcomes for partial success. The matching MCP tools are documented in the MCP guide.