Help

Changelog

Client API version history.

Version numbers match info.version on this API.

Breaking changes increment the major version. Additive endpoints and fields increment minor. Patch is reserved for documentation-only or non-contract fixes.


1.15.0

CRM-ready webhook identity on every lead email event

Added

  • Shared lead identity block on email.sent, reply.received, reply.categorized, and bounce.detected: email, mailbox_email, campaign_name, contact fields, and nested custom_fields
  • email.sent body_text (plain text, 16,000 character cap) plus step_number / node_id / flow_node_id when known
  • bounce.detected explicit email and reason (severity + SMTP code)
  • Block list group: blocklist.entry_added and blocklist.entry_removed for every block_list insert or delete (inbox, API, reply opt-out, import, bounce suppression). Email rows may include the lead identity block. Domain rows send the host only (example.com) with no email or identity fields. A hard bounce may emit both bounce.detected and blocklist.entry_added
  • custom_fields_truncated: true when custom fields exceed the 8 KB byte budget

Changed

  • Existing event keys are unchanged. Empty contact fields are omitted rather than sent as empty strings.

1.14.0

Campaign start and pause dates

Added

  • lifecycle_schedule on campaign create/update/detail: time_zone, nullable start_on/pause_on calendar dates, and read-only derived start_at/pause_at
  • Campaign status scheduled for launches with a future start_on
  • Launch returns running or scheduled plus the saved lifecycle_schedule

Changed

  • Empty start_on still launches immediately. Empty pause_on never auto-pauses. pause_on is exclusive: sending stops before that local day.

1.13.0

Webhook identity fields for CRM sync

Added

  • email.sent data now includes email (lead recipient), mailbox_email, and campaign_name so CRM integrations can match contacts without a Furnace API key
  • reply.received data now includes body_text (plain-text display body, quoted thread stripped, truncated at 16,000 characters), plus mailbox_email and campaign_name

Changed

  • Existing email.sent / reply.received keys are unchanged. Omitted new fields are not sent as empty strings; campaign_name may be null if the campaign row has no name.

1.12.0

Lead tags and email verification on import

Added

  • Optional tags (array of names/aliases) and email_verification on LeadCreate — create, bulk, async, and staged import all inherit the same fields
  • Person-level lead tags (catalog + account-owned) resolved by name; unknown names find-or-create an account tag
  • Structured verification facts (ok / catch_all / invalid / unknown / disposable) stored separately from tags

Changed

  • Omitting the new fields behaves exactly as 1.11.0. additionalProperties: false still rejects unknown keys such as mv_result.

1.11.0

Bulk-first MCP / Client API

Added

  • GET /v1/meta/limits — page sizes, sync/async caps, queued vs running job quotas, supported scopes/operations, file-ingress capabilities
  • POST /v1/bulk/preview — estimate matched/excluded/actionable counts; bind execution with preview_id
  • Staged lead import: POST /v1/campaigns/{id}/imports/staged, POST /v1/jobs/{id}/staging-rows, POST /v1/jobs/{id}/finalize
  • Optional POST /v1/uploads/presign for direct S3 CSV upload (upload_id); local filesystem paths are never accepted
  • POST /v1/people/export (exportPeople) and compact email/global_lead_id projection
  • POST /v1/campaigns/{id}/enroll (enrollPeople) with server-side scope + exclusions
  • POST /v1/lead-lists/{id}/members:bulk (updateLeadListMembership) async add/remove
  • POST /v1/jobs/{id}/cancel — cancel queued/uploading immediately; stop running jobs between chunks
  • Job operations: add_to_lead_list, remove_from_lead_list, export_leads, csv_lead_import_staged
  • Campaign detail now returns attached mailbox_ids

Changed

  • Async job capacity: only running jobs consume the concurrent slot (default 3); additional jobs stay queued up to a separate quota
  • createAsyncJob accepts scope, exclusions, preview_id, target_list_id, source_campaign_id, and export projection fields
  • Lead-source bucketId is normalized to the campaign bucket on create/save; richText variants derive body_html from template/body_text when empty

1.10.0

Campaign create defaults to Central business hours

Changed

  • POST /v1/campaigns now defaults omitted schedule to Central 9–5 Mon–Fri (America/Chicago). Pass "schedule": null for 24/7.
  • Omitted sending_interval_seconds defaults to 1440 (24 minutes; ~20 emails per mailbox per day on the default window), replacing the previous 300 default.

1.9.0

Replace lead preview + structured errors

Added

  • GET /v1/threads/{id}/replace-lead/preview?email= — read-only preview of create vs attach, block-list status, match count, and whether the write would be refused (allowed / disallowed_reason)
  • MCP tool previewThreadLeadReplacement (auto-generated from the new endpoint)
  • POST /v1/threads/{id}/replace-lead accepts new_mobile_phone_number
  • The same response returns target_lead_id: the pre-existing contact on mode = attached, otherwise null

Changed

  • Replace-lead business-rule failures now return structured 400/403/404/409 instead of opaque 500s (same_as_current_lead, lead_already_replaced, target_missing_enrollment, target_already_replaced, lead_not_found, invalid_reason, …)
  • replaceThreadLead description documents create vs attach side effects and points agents at the preview tool

1.8.0

Replace lead reuses an existing campaign contact

Added

  • POST /v1/threads/{id}/replace-lead returns mode: attached when the replacement address was already a live lead in the campaign, created otherwise
  • The same response returns retired_sibling_count, how many duplicate rows of that address had their sequence stopped

Changed

  • Replacing to an address that is already in the campaign no longer creates a second lead. The existing contact is reused, the conversation moves to them, and the replaced lead is retired as stopped/replaced instead of archived. new_lead_id is that pre-existing contact.
  • The call now fails if the existing contact has no enrollment in the campaign, since the forward would have nothing to send against

1.7.0

Account settings + MCP surface

Added

  • GET/PUT /v1/webhooks — account webhook URL, signing secret, enabled events
  • GET/POST /v1/api-keys, DELETE /v1/api-keys/{id} — create returns secret once; list omits secret
  • POST/GET /v1/mailboxes/connect-sessions — start mailbox connect handoff and poll status

1.6.1

People response shape + request body hygiene

Changed

  • GET /v1/people and lead-list people pages now return the same person fields as detail/PATCH, with latest_activity_at (list no longer emits latest_activity or per-row total_count)
  • PATCH /v1/campaigns/{id} accepts "schedule": null to clear the send window (24/7)
  • Unknown keys on primary request bodies are ignored (stripped) so handlers match closed OpenAPI schemas

1.6.0

Inbox triage timestamps

Added

  • Thread responses include last_inbound_at — latest inbound lead reply timestamp

Changed

  • GET /v1/threads date_from / date_to and Newest/Oldest sort now use last_inbound_at (lead reply time), not last_message_at
  • last_message_at remains latest activity in either direction

1.5.0

Inbox thread search

Changed

  • GET /v1/threads?q= — free-text search now matches subject, participants, lead name/email/company, campaign name, thread tags, and message bodies (prefix/FTS; minimum 2 characters)

1.4.3

Self-hosted docs rebuild (Fumadocs + OpenAPI reference + agent layer)

Changed

  • Replaced Starlight/Scalar with a unified Fumadocs site at /docs
  • API reference at /docs/reference/ uses fumadocs-openapi inside the Furnace docs shell (read-only, no try-it console)
  • Documentation and API Reference are separated in the header (Mintlify-style tabs)
  • Split building campaigns into quickstart, flow, launch, and flow-schemas guides
  • Auto-generated llms.txt, llms-full.txt, and per-page .md mirrors for agent access

1.4.2

Starlight documentation site

Changed

  • Replaced Scalar at /docs with a Starlight static docs site (guides + OpenAPI reference via starlight-openapi)
  • Removed phantom /documentation/* OpenAPI paths; guides export from TS builders at build time
  • Building campaigns guide now documents POST /flow as the hero save (PUT remains a deprecated alias)

1.4.1

Documentation consolidation

Changed

  • Removed the Campaign flow reference guide page — field-level flow object docs now live in Models (CampaignFlow, FlowUpdate, FlowValidationIssue, and related node schemas)
  • Building campaigns guide and flow API endpoint descriptions now link to Models schemas

1.4.0

Campaign build lifecycle & flow pipeline

Added

  • Building campaigns guide in /docs (Guide → Building campaigns) with lifecycle rules, copy-pasteable flow JSON, and draft-vs-live locking behavior
  • Campaign flow reference guide (/documentation/campaign-flow-reference) — field-by-field flow object reference, merge variables, normalization rules, and full validation error-code catalog
  • POST /v1/campaigns — create a draft campaign with optional mailboxes, tags, schedule, and initial flow
  • POST /v1/campaigns/{id}/flow — hero flow save with flow_revision, field_sync, and optional If-Match concurrency
  • POST /v1/campaigns/{id}/flow?dry_run=true — dry-run alias for flow validation without persisting
  • PUT /v1/campaigns/{id}/flow — write the canonical campaign flow payload (deprecated alias of POST)
  • POST /v1/campaigns/{id}/flow:validate — dry-run normalization, validation, and lifecycle gating
  • PATCH /v1/campaigns/{id}/status — pause, resume, or stop live campaigns (running | paused | stopped)
  • PATCH /v1/campaigns/{id}/flow/nodes/{nodeId} — live content-only node patch
  • GET /v1/flow-templates — starter flow graphs
  • GET /v1/campaigns/{id}?include=launch_state,lead_field_state — checklist observability without extra validate calls
  • POST /v1/campaigns/{id}/launch — start a draft campaign after backfilling enrollments
  • field_sync on flow saves — auto-declares merge-variable fields from email copy

Changed

  • GET /v1/campaigns list responses omit flow_data; use GET /v1/campaigns/{id} for the full flow
  • Campaign detail responses include computed flow_revision
  • POST /v1/campaigns/{id}/launch returns { enrolled: N } and uses shared launch validation
  • Live campaign flows are now topology-locked in both the API and the builder UI. Structural edits return 403 permission_error with code flow_locked.
  • POST /v1/campaigns/{id}/lead-fields now writes flow data through the same service-role-safe persistence path as the new flow endpoints.
  • Building campaigns guide expanded with end-to-end curl walkthrough, flow:validate response examples, structural change reason codes, launch preconditions, and troubleshooting table
  • OpenAPI schemas for flow node types (EmailVariant, LeadSourceNodeData, EmailNodeData, WaitTimeNodeData, AICategorizerNodeData, DataSenderNodeData, FlowNode, FlowEdge, FlowValidateResult) now include per-field descriptions and examples

1.3.0

Webhooks — categorization and delivery infrastructure

Added

  • Outbound webhook reply.categorized when a thread reply category is assigned, changed, or cleared
  • Granular per-event webhook subscription in Account Settings (expand event groups to pick individual types)

Changed

  • Campaign pause, resume, and stop from the Furnace app now emit campaign.paused, campaign.resumed, and campaign.stopped webhooks (previously Client API only)
  • PATCH /v1/threads/{id} category updates emit reply.categorized

1.2.0

Inbox expansion — triage, outbound messaging, and ops endpoints for programmatic inbox use.

Added

  • Webhooks guide in /docs (Guide → Webhooks) with example payloads for every outbound event type
  • Consolidated /docs into a single Scalar document with Guide and API sidebar sections

Thread list & triage

  • GET /v1/threads — new query params: q, unread_only, conversation_status, category (no_category for uncategorized), tag_ids, date_from, date_to, has_reply_only (default true)
  • PATCH /v1/threads/{id} — partial update: category, conversation_status, read

Outbound messaging

  • POST /v1/threads/{id}/forward — queue forward job (forward_message_id required)
  • GET /v1/message-jobs/{id} — poll reply/forward job status
  • POST /v1/message-jobs/{id}/cancel — cancel queued/failed outbound job
  • POST /v1/message-jobs/{id}/send-now — expedite queued outbound job

Inbox ops

  • PUT /v1/threads/{id}/out-of-office — set OOO (resume_mode: scheduled | instant | none)
  • DELETE /v1/threads/{id}/out-of-office — clear OOO
  • POST /v1/threads/{id}/replace-lead — replace thread lead; optional forward_message_id
  • GET /v1/thread-tags — list account thread tags
  • POST /v1/threads/{id}/tags:add / tags:remove — assign or remove tag on thread

Changed

  • POST /v1/threads/{id}/reply — optional in_reply_to_message_id (defaults to latest message)

Notes

  • Poll outbound sends with /v1/message-jobs/{id}, not /v1/jobs/{id} (import jobs only).
  • Tag create/edit/delete remains in the Furnace app; the API supports list + assign/remove only.

1.1.0

People, lists, jobs, and batch webhooks

Added

  • GET/PATCH /v1/people, GET/PATCH /v1/people/{globalLeadId}
  • GET/POST/PATCH/DELETE /v1/lead-lists, list membership endpoints
  • POST /v1/jobs, GET /v1/jobs/{id} — async bulk operations
  • Campaign/mailbox tag CRUD and filtering
  • Sync bulk shortcuts: leads:add, leads:remove, leads:remove-from-all-campaigns, enrollment pause/resume
  • Batch completion webhooks (*.completed) for bulk and enrollment actions

Changed

  • Webhook allowlist: removed enrollment.created / enrollment.updated; added batch completion events

1.0.0

Initial Client API

Added

  • Campaigns, leads, mailboxes, block list, campaign stats
  • Basic inbox: GET /v1/threads, GET /v1/threads/{id}, GET /v1/threads/{id}/messages, POST /v1/threads/{id}/reply
  • Atomic webhooks: lead.*, campaign lifecycle, email.sent, reply.received, bounce.detected
  • OpenAPI at /openapi.json, Scalar UI at /docs