Generate Batch (multiple leads)

ReferenceUpdated June 14, 2026

Generate Batch (multiple leads)

Generate personalized cold email sequences for multiple leads in one request. The API accepts the batch and returns immediately with a list_id. Processing runs asynchronously; you poll the list status and then export results when completed.

POST /api/v1/campaigns/:id/generate-batch · scope campaigns:write

You can submit a batch before the build finishes. As soon as value propositions are selected, the campaign is eligible for generation — you do not need to wait for build-status overall to reach ready. Batches submitted while the build is still in progress (overall: "building") are accepted and queued; processing begins automatically once the build completes. Submitting before value propositions are selected returns 400 BAD_REQUEST (campaign setup incomplete).


Path parameters

ParameterTypeDescription
idstring (UUID)Campaign ID (from GET /api/v1/campaigns).

Headers

HeaderRequiredDescription
Authorization or X-API-KeyYesAPI key.
Content-TypeYesapplication/json

Request body

FieldTypeRequiredDescription
leadsarrayYesArray of lead objects (at least one). Each lead must include a valid email.
leads[].namestringNoFull name.
leads[].titlestringNoJob title.
leads[].companystringNoCompany name.
leads[].emailstringYesEmail (required; used for mapping and export).
leads[].linkedin_urlstringNoLinkedIn profile URL.
leads[].company_websitestringNoCompany website.
optionsobjectYesGeneration configuration (see fields below). email_count and a signature are required.
options.email_countnumberYesEmails to generate per lead. Integer 1–4.
options.email_signaturestringYes*Sender signature, inline. Required unless signature_id is provided. Multi-line: use \n between lines. See Signature format below.
options.signature_idstring (UUID)Yes*ID of a saved signature (from GET /api/v1/signatures) to use instead of email_signature. Provide exactly one of email_signature or signature_id.
options.list_namestringNoDisplay name for the generated list. Defaults to API Batch (N leads).
options.enrichment_enabledbooleanNoWhen true, runs web research per lead before writing (each lead costs 2 credits instead of 1). Requires an enrichment signal on every lead — see Enrichment requirements.
options.notification_emailstringNoEmail address to receive the "processing complete" notification (with a link to the processed list). Must be a valid email. If omitted, the notification is sent to the workspace owner.
options.additional_detailsstringNoFree-text campaign context passed to the writer ("Added Campaign Details") — angle, constraints, or instructions that override defaults.
options.approved_ctasstring[] | stringNoCTA types to use. Defaults to Question CTA, Lead Magnet CTA, Direct Meeting CTA.

* Exactly one of email_signature or signature_id is required (providing both is a 400).

Note: campaign_angle is a deprecated alias of additional_details, and sequence_name is a deprecated alias of list_name. Prefer the new names.

Completion notifications. When a batch finishes processing in the background, MachFive sends a "processing complete" email containing a link to the processed list. By default this goes to the workspace owner. Set options.notification_email to send it to a different address instead. (The single-lead generate endpoint returns results synchronously in the response and does not send a notification email.)

Signature format

The signature is required so the writer never fabricates sender details. Send it as a single string with \n line breaks; each line is rendered on its own line in the email. Best-practice cold-email structure:

Name
Company Name | Position
Company Address

As JSON:

"email_signature": "Jane Doe\nAcme Inc | VP Marketing\n123 Main St, Springfield, IL 62701"

To reuse a saved signature instead, omit email_signature and pass signature_id (manage saved signatures via Signatures):

"signature_id": "f3a9c2e1-..."

Enrichment requirements

When enrichment_enabled is true, every lead must include at least one research signal: company, linkedin_url, or company_website. A company value also lets the system extract the email domain and cross-reference it against the company name before researching. A lead with none of these returns a 400 (enrichment would have nothing to work with).


Example request

curl -X POST "https://app.machfive.io/api/v1/campaigns/CAMPAIGN_ID/generate-batch" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "leads": [
      { "name": "Jane Doe", "title": "VP Marketing", "company": "Acme Inc", "email": "jane@acme.com" },
      { "name": "John Smith", "title": "CTO", "company": "Beta Co", "email": "john@beta.co" }
    ],
    "options": {
      "email_count": 3,
      "email_signature": "Sam Rivera\nMachFive | Founder\n500 Market St, San Francisco, CA 94105",
      "list_name": "API Batch Q1",
      "enrichment_enabled": true,
      "notification_email": "ops@yourcompany.com",
      "additional_details": "Lead with the deliverability angle; keep it under 90 words."
    }
  }'

Response (202 Accepted)

The request returns immediately. Processing continues in the background.

{
  "list_id": "uuid-of-email_sequences-row",
  "status": "processing",
  "leads_count": 2,
  "message": "Batch accepted. Processing will continue in the background. Poll list status or open in the UI."
}

The response may also include sequence_id (deprecated); use list_id only.

FieldTypeDescription
list_idstring (UUID)Use this to poll GET /api/v1/lists/:list_id and to export with GET /api/v1/lists/:list_id/export.
statusstring"processing".
leads_countnumberNumber of leads accepted for processing.
messagestringHuman-readable confirmation.

Next steps

  1. Poll GET /api/v1/lists/:list_id until processing_status is completed or failed.
  2. When completed, call GET /api/v1/lists/:list_id/export?format=csv or ?format=json to download results.

See Lists for list status and Export for download details.


Error responses

StatusErrorDescription
400BAD_REQUESTInvalid JSON; missing leads; a lead missing/invalid email; email_count missing or not 1–4; no signature (neither email_signature nor signature_id) or both provided; an invalid options.notification_email; enrichment_enabled with a lead missing all of company/linkedin_url/company_website; or campaign setup is incomplete (no knowledge base yet and value propositions not completed).
401UNAUTHORIZEDMissing or invalid API key.
402INSUFFICIENT_CREDITSNot enough credits for this many leads (1 per lead, or 2 with enrichment enabled). detail includes { required, available, payg_enabled, pct_of_cap }.
403FORBIDDENCampaign not in this workspace.
404NOT_FOUNDCampaign not found, or signature_id not found in this workspace.
429RATE_LIMITEDPer-key rate limit exceeded; honor Retry-After.
429WORKSPACE_LIMITToo many concurrent batch jobs; try again later.
500INTERNAL_ERRORFailed to enqueue or create list.

Error body: { "error": "CODE", "message": "...", "detail"?: ..., "request_id": "..." }.

Note: This endpoint does not support Idempotency-Key. A retried request enqueues a new batch. Credits are deducted on-success per completed lead. See Conventions → Idempotency for the endpoints that do.