AI-readable Zevari documentation snapshot
Zevari API Playbooks
Ordered API playbooks for developers and AI agents building Zevari workflows over the public REST API.
Requested URL: https://docs.zevari.ai/api/playbooks
Where This Sits
API Playbooks is the call-order guide for developers, scheduled runners, CRM integrations, internal tools, and AI agents using the public REST API. Use the API Reference for endpoint schemas. Use MCP Reference for MCP tool semantics. Use Help Workflows for human-facing Zevari workflow concepts.
Operating Principles
- Use the playbooks for order of operations
The API reference tells you the exact schema for one endpoint. API Playbooks tell you which endpoint to call first, which response fields to preserve, and what to do next.
- Treat the API key as the active context
A Zevari API key is bound to an organization and active LinkedIn sender. Do not invent workspace, account, or sender IDs that are not returned by Zevari.
- Stop at approval boundaries
LinkedIn sends, public posts, campaign activation, and other sensitive writes require confirmations.requestAction before the write endpoint executes.
- Read safety before scheduling writes
Call safety.getStatus before queued LinkedIn work. If safetyPaused is true, hold or route work according to the pause fields instead of firing into a blocked sender.
- Preserve request IDs and docs URLs
Every API error includes request_id plus error docs and suggested action fields. Preserve those values in logs and support handoffs.
Confirmation Action Types
When staging a confirmation, use the action_type that matches the endpoint you will execute after approval.
- linkedin.sendConnectionRequest
Use confirmations.requestAction with action_type linkedin_send_connection_request before executing linkedin.sendConnectionRequest.
- linkedin.sendMessage
Use confirmations.requestAction with action_type linkedin_send_message before executing linkedin.sendMessage.
- linkedin.sendInMail
Use confirmations.requestAction with action_type linkedin_send_inmail before executing linkedin.sendInMail.
- linkedin.createPost
Use confirmations.requestAction with action_type linkedin_create_post before executing linkedin.createPost.
- linkedin.commentOnPost
Use confirmations.requestAction with action_type linkedin_comment_on_post before executing linkedin.commentOnPost.
- linkedin.reactToPost
Use confirmations.requestAction with action_type linkedin_react_to_post before executing linkedin.reactToPost.
- campaigns.updateStatus status=active
Use confirmations.requestAction with action_type campaign_activate before executing campaigns.updateStatus status=active.
Bootstrap an API Runner
Discover the public API surface, verify the API key context, and check LinkedIn safety before planning work. Methods: GET /v1/methods, profile.get, safety.getStatus, libraryContext.get.
- 1. List the public methods
Fetch /v1/methods at startup or during tool discovery. Use the returned method names, paths, summaries, and docs URLs as the source of truth. Example: curl -sS https://api.zevari.ai/v1/methods \
-H "Authorization: Bearer $ZEVARI_API_KEY"
- 2. Read the business profile
Call profile.get to understand the workspace voice, company context, ICP, and defaults before generating copy or scoring leads. Example: curl -sS -X POST https://api.zevari.ai/v1/profile/get \
-H "Authorization: Bearer $ZEVARI_API_KEY" \
-H "Content-Type: application/json" \
-d '{}'
- 3. Check LinkedIn safety
Call safety.getStatus before queueing LinkedIn writes. If safetyPaused is true, do not call send endpoints until the status says active or the response provides an auto-resume timestamp you can schedule around. Example: curl -sS -X POST https://api.zevari.ai/v1/safety/getStatus \
-H "Authorization: Bearer $ZEVARI_API_KEY" \
-H "Content-Type: application/json" \
-d '{}'
- 4. Load Library context only when generation needs it
Call libraryContext.get before generating outreach, campaign copy, or content that should reflect saved templates and brand context.
- Note 1
Use OpenAPI for exact schemas; use this playbook to decide call order.
- Note 2
API runners should cache method discovery briefly but refresh after deployment or schema errors.
Run an Approval-Gated LinkedIn Write
Stage the exact write payload, wait for approval or Autopilot, then execute the write endpoint with the returned confirmation_id. Methods: confirmations.requestAction, linkedin.sendConnectionRequest, linkedin.sendMessage, linkedin.sendInMail, linkedin.createPost, linkedin.commentOnPost, linkedin.reactToPost.
- 1. Build the exact executable payload
Use the target write endpoint's exact field names. For example, connection requests use identifier and optional note; messages use chatId or recipientId plus message.
- 2. Apply sender-tier note limits before staging
For linkedin_send_connection_request, cap note to the active sender's LinkedIn tier before calling confirmations.requestAction: free senders support 200 characters; premium and sales_navigator senders support 300. If you exceed the active sender's limit, staging or execution returns HTTP 400 with ok=false and data.error='connection_note_too_long'. Treat that as a payload error, shorten the note, and stage a new confirmation.
- 3. Stage confirmation
Call confirmations.requestAction with the action_type that matches the write endpoint and the exact payload you intend to execute. Example: curl -sS -X POST https://api.zevari.ai/v1/confirmations/requestAction \
-H "Authorization: Bearer $ZEVARI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"action_type": "linkedin_send_connection_request",
"payload": {
"identifier": "ACoAAAexample",
"note": "Saw your post on AI workflow ops. Open to connecting?"
}
}'
- 4. Branch on Autopilot
If data.autopilot.approved is true, immediately call the write endpoint with data.confirmation_id. If not, store data.approval_url, show it to the user, and wait until they approve in Zevari.
- 5. Execute with confirmation_id
Retry the original write endpoint with the approved confirmation_id. Do not edit the payload between confirmation and execution. Example: curl -sS -X POST https://api.zevari.ai/v1/linkedin/sendConnectionRequest \
-H "Authorization: Bearer $ZEVARI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"identifier": "ACoAAAexample",
"note": "Saw your post on AI workflow ops. Open to connecting?",
"confirmation_id": "pac_..."
}'
- 6. Handle drift or expiry
If approval expires or the payload drifts, stage a new confirmation with the current exact payload. An explicitly rejected personalized enrollment is terminal for that idempotency key: stop, and use a new key only when the user makes a new request.
- Note 1
REST clients should not use MCP-only chat approval tools.
- Note 2
Do not reuse a confirmation_id after changing an over-limit connection note; stage a fresh confirmation with the shortened note.
- Note 3
For two or more outbound LinkedIn writes in one planned batch, use the bulk-confirmation pattern when available instead of staging separate approval URLs.
Create and Launch a Campaign
Create a fixed or continuous draft campaign, follow its returned next action, then activate it with approval. Methods: campaigns.create, campaigns.validate, confirmations.requestAction, campaigns.updateStatus, campaigns.addTargets, campaigns.getProgress.
- 1. Create the campaign as a draft
Call campaigns.create with targets, step configuration, generated content, and enrollment_mode. Enrollment defaults to fixed; use continuous whenever the campaign should keep accepting new leads after launch. Continuous campaigns are not limited to generic or template-resolvable copy — personalization_mode is independent of enrollment_mode, so a continuous campaign can carry full per-lead personalization via personalized_steps and/or sequence_override on individual targets, same as fixed. Send enrollment_mode as a top-level field, never nested under settings; a settings-only enrollment_mode now returns a loud warning telling you to delete the draft and recreate it with the field top-level, rather than silently defaulting. Creation persists a draft and returns status, effective enrollment_mode, targets_editable, add_targets_method, and next_action; it does not launch sending.
- 2. Validate before launch
Call campaigns.validate or inspect the creation response for missing targets, unsafe step configuration, unsupported action types, or sender readiness issues.
- 3. Stage activation approval
Campaign activation is approval-gated. Stage a confirmation with action_type campaign_activate and payload containing the campaign_id. Example: curl -sS -X POST https://api.zevari.ai/v1/confirmations/requestAction \
-H "Authorization: Bearer $ZEVARI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"action_type": "campaign_activate",
"payload": { "campaign_id": "campaign_..." }
}'
- 4. Activate after approval
When Autopilot approves or the user approves in the browser, call campaigns.updateStatus with status active and the same confirmation_id. Example: curl -sS -X PATCH https://api.zevari.ai/v1/campaigns/updateStatus \
-H "Authorization: Bearer $ZEVARI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"campaign_id": "campaign_...",
"status": "active",
"confirmation_id": "pac_..."
}'
- 5. Append leads with shared campaign copy
For an active continuous campaign, call campaigns.addTargets once with a stable idempotency key and omit personalized_steps; accepted targets use the executable shared campaign copy and are scheduled atomically. Draft/paused additions remain unscheduled; terminal campaigns require a new campaign. Example: curl -sS -X POST https://api.zevari.ai/v1/campaigns/addTargets \
-H "Authorization: Bearer $ZEVARI_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: crm-sync-2026-07-19-batch-0042" \
-d '{
"campaign_id": "campaign_...",
"idempotency_key": "crm-sync-2026-07-19-batch-0042",
"targets": [{
"lead_id": "lead_...",
"linkedin_provider_id": "ACoAAAexample",
"name": "Jane Founder"
}]
}'
- 6. Append per-lead copy and/or a per-lead sequence shape without pausing
Add recipients with campaigns.addTargets. Fixed and continuous campaigns accept two independent personalization mechanisms per target, and a single target may use one or both together: personalized_steps overrides that lead's message copy (a full text override per step, validated and snapshotted); sequence_override overrides that lead's step shape entirely (its own ordered list of step types, e.g. view_profile -> comment -> connection_request-with-note -> follow-ups, instead of the campaign's default steps). Complete personalized additions apply to already-active fixed or continuous campaigns without pausing them and without resetting other targets' timers. Use a stable idempotency_key. Eligible Autopilot applies; otherwise show approval link, approve confirmation_id, and retry identically. Same payload replays; changed payload conflicts; rejection terminates the key. A new key requires a new user request. Existing recipients and shared campaign steps remain unchanged. Approved content is immutable; active targets follow campaign timing. Missing copy: PERSONALIZED_SEQUENCE_INCOMPLETE. Step drift before activation: CAMPAIGN_PERSONALIZED_SNAPSHOT_INVALID. Example: curl -sS -X POST https://api.zevari.ai/v1/campaigns/addTargets \
-H "Authorization: Bearer $ZEVARI_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: crm-personalized-jane-mia-2026-07-22" \
-d '{
"campaign_id": "campaign_...",
"idempotency_key": "crm-personalized-jane-mia-2026-07-22",
"targets": [
{
"lead_id": "lead_jane",
"linkedin_provider_id": "ACoAAAexample1",
"name": "Jane Founder",
"personalized_steps": [
{
"step_order": 1,
"message": "Jane, your approach to revenue operations stood out. Open to connecting?"
},
{
"step_order": 2,
"body": "Thanks for connecting, Jane. Your founder-led sales system mirrors what we see with AI teams."
}
]
},
{
"lead_id": "lead_mia",
"linkedin_provider_id": "ACoAAAexample2",
"name": "Mia Operator",
"sequence_override": [
{ "step_order": 1, "type": "view_profile" },
{ "step_order": 2, "type": "comment" },
{ "step_order": 3, "type": "connection_request", "note": "Enjoyed your take on ops tooling." },
{ "step_order": 4, "type": "follow_up_message", "message": "Following up on the connection, Mia." }
]
}
]
}'
# If approval is pending, repeat the exact request after approval and add:
# "confirmation_id": "pac_..."
- 7. Monitor progress
Call campaigns.getProgress for counts, target states, blocked conditions, and recent execution outcomes. If safety pauses the sender, hold new activation and scheduling work until safety clears.
Search LinkedIn and Save Targets
Page through LinkedIn search results, normalize prospects, save targets, and optionally attach them to a campaign. Methods: linkedin.searchProfiles, targets.save, targets.createList, campaigns.addTargets.
- 1. Search with a stable query
Call linkedin.searchProfiles with the query, filters, and limit. Keep the same request body while paging. Example: curl -sS -X POST https://api.zevari.ai/v1/linkedin/searchProfiles \
-H "Authorization: Bearer $ZEVARI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"query": "founder AI agency",
"job_titles": ["Founder"],
"locations": ["United States"],
"limit": 50
}'
- 2. Use next_cursor for pagination
If data.has_more is true and data.next_cursor is present, repeat the same search body with cursor set to that value. Stop when has_more is false.
- 3. Save usable targets
Call targets.save or targets.createList with the profiles you actually want to pursue. Keep provider IDs and LinkedIn URLs from the search result; do not synthesize them.
- 4. Add targets to a campaign when ready
Call campaigns.addTargets after the campaign exists and targets are reviewed. Send the same stable value as body idempotency_key and Idempotency-Key header. Omit personalized_steps to use shared copy in an active continuous campaign. For a new recipient's exact sequence, supply complete personalized_steps; active fixed and continuous campaigns stage approval and enroll without pausing. If manual approval is required, approve and repeat the identical request with confirmation_id. Draft/paused additions stay unscheduled; terminal campaigns require a new campaign. Follow content_mode, snapshot provenance, dispositions, error_code, and next_action.
- Note 1
Search endpoints are provider-backed and safety-scoped. Respect rate-limit and safety responses instead of looping aggressively.
- Note 2
Cursors are opaque. Do not parse or alter them.
Triage Inbox and Send a Reply
Read inbox context, classify or research the sender, generate a reply, stage approval, then send the message. Methods: linkedin.getInbox, linkedin.getMessages, agents.researchPerson, agents.generateMessages, confirmations.requestAction, linkedin.sendMessage.
- 1. List inbox threads
Call linkedin.getInbox to find the active thread or lead conversation. Store the chatId returned by Zevari.
- 2. Read message history
Call linkedin.getMessages with the chatId before drafting a reply. Do not reply from stale or partial context.
- 3. Research and draft
Use agents.researchPerson, agents.behavioralProfile, or agents.generateMessages when the reply needs personalization. The output is a draft, not permission to send.
- 4. Stage and execute
Call confirmations.requestAction with action_type linkedin_send_message and payload containing chatId and message. After approval, call linkedin.sendMessage with the same chatId, message, and confirmation_id.
- 5. Protect against stale replies
If you track expected_last_inbound_at, include it so Zevari can block replies when the lead has responded since the draft was prepared.
Save, Review, and Publish Content
Create content drafts through the API, keep publishing approval-gated, and use LinkedIn content endpoints only after confirmation. Methods: content.save, content.list, content.update, confirmations.requestAction, linkedin.createPost, linkedin.reactToPost, linkedin.commentOnPost.
- 1. Save draft content
Call content.save for drafts and content.update for revisions. Saving internal content is not the same as publishing to LinkedIn.
- 2. Stage LinkedIn publishing separately
When a public LinkedIn post is ready, stage a confirmation with action_type linkedin_create_post and payload containing the exact post content.
- 3. Publish with confirmation_id
Call linkedin.createPost only after approval. Preserve confirmation_id and the exact approved content.
- 4. Engage with existing posts carefully
For comments and reactions, stage linkedin_comment_on_post or linkedin_react_to_post first. Use provider post IDs returned by Zevari or LinkedIn search/read endpoints.
Handle Safety Pauses and Circuit Breakers
Use safety.getStatus to decide whether to wait, retry, contact support, or remove a sender from rotation. Methods: safety.getStatus, linkedin.getSafetyStatus.
- 1. Read status before queued sends
Call safety.getStatus for the active API key context before releasing queued LinkedIn outreach.
- 2. Pause on currentStatus
If currentStatus is paused_circuit_breaker or safetyPaused is true, stop LinkedIn writes for that sender. Do not keep retrying failed sends.
- 3. Schedule from absolute time
If autoResumes is true and resumesAt or cooldownEndsAt is present, hold queued work until that ISO timestamp, then refresh status before releasing the queue.
- 4. Use diagnostic fields for support
Capture pauseReasonDetail, triggeringActionType, failureCount, failureThreshold, upstreamErrorCodes, and requestIds. Include those in support handoffs.
- 5. Do not automate manual resume
If autoResumes is false or resumesAt is null, follow resolutionHint. Public REST does not expose linkedin.resumeAll because it mutates account-wide safety state.
Handle API Errors
Preserve Zevari's structured error envelope and recover by reading docs_url and suggested_action before retrying. Methods: All methods.
- 1. Log the whole envelope
Store request_id, error.code, error.message, error.docs_url, error.suggested_action, method, and any validation details.
- 2. Use HTTP status for transport, error.code for behavior
A 401 means API key/auth context. A 400 may be invalid arguments, missing confirmation, payload drift, or safety denial. A 429 means rate limiting. The error.code and suggested_action tell you what to do next.
- 3. Retry only after correcting the cause
Do not blindly retry confirmation errors, safety pauses, invalid arguments, unsupported methods, or stale approvals. Read docs_url and rebuild the request if necessary.
- 4. Escalate with request_id
When contacting Zevari support, include request_id, endpoint path, method, timestamp, active workspace/sender if known, and the exact error fields.
Check which leads replied to a campaign email
Poll campaign progress for reply counts, list the leads that replied with their reply bodies, read the full email thread for one target, then route warm replies into pipeline. Methods: campaigns.getProgress, campaigns.getReplies, leads.getEmailThread.
- 1. Poll progress for reply counts
Call campaigns.getProgress for the campaign to see aggregate counts including how many targets have replied. Use this to decide whether there are new responders worth pulling before listing every reply. Example: curl -sS -G https://api.zevari.ai/v1/campaigns/getProgress \
-H "Authorization: Bearer $ZEVARI_API_KEY" \
--data-urlencode "campaign_id=cmp_..."
- 2. List who replied and what they said
Call campaigns.getReplies to list inbound email replies across the campaign. Each entry returns reply_id, campaign_target_id, lead_id, lead_name, lead_email, from_email, subject, text_preview (first 1000 chars), text_truncated, occurred_at, matched_by, and forwarded. Bodies carry an untrusted-input warning. Paginate older pages by passing the previous response's next_before and next_before_id as before and before_id; both are only set when count equals limit. Example: curl -sS -G https://api.zevari.ai/v1/campaigns/getReplies \
-H "Authorization: Bearer $ZEVARI_API_KEY" \
--data-urlencode "campaign_id=cmp_..." \
--data-urlencode "limit=50"
- 3. Read the full back-and-forth for a target
Call leads.getEmailThread with the campaign_target_id (or lead_id) from a reply to get the full conversation: inbound replies interleaved with outbound campaign emails, merged and sorted ascending by timestamp. Use this for the complete text rather than relying on the truncated preview in the list. Inbound bodies carry an untrusted-input warning. Example: curl -sS -G https://api.zevari.ai/v1/leads/getEmailThread \
-H "Authorization: Bearer $ZEVARI_API_KEY" \
--data-urlencode "campaign_target_id=ct_..." \
--data-urlencode "limit=100"
- 4. Route warm replies into pipeline
When a reply is a genuine response worth pursuing, stage the next action (pipeline opportunity, meeting, or a LinkedIn/email follow-up) through the normal approval-gated write path. Preserve campaign_target_id and lead_id so the follow-up attaches to the right record.
- Note 1
Email replies surface alongside LinkedIn replies; campaigns.getReplies covers the email channel specifically.
- Note 2
Reply bodies may be large. campaigns.getReplies returns a preview per reply, while leads.getEmailThread returns the full text for one target.
- Note 3
Respect pagination via the keyset cursor: pass next_before and next_before_id as before and before_id to fetch the next older page, and stop when next_before is null.
Read Back the Audit Trail After a Write
Confirm exactly what happened to a write with actions.getReceipt, or page a lead's full action history with actions.listForLead, instead of re-querying from scratch. Methods: actions.getReceipt, actions.listForLead.
- 1. Look up one receipt
Every priority LinkedIn write (send_message, send_inmail, send_connection_request, create_post, targets_save, leads_lookup_by_url, and others) returns action.receipt_id on the write response. Call actions.getReceipt with that receipt_id to pull the receipt plus its linked confirmation, request, queue, and audit evidence, LinkedIn result IDs, safety snapshot, and hydrated lead context in one call. Example: curl -sS -G https://api.zevari.ai/v2/actions/getReceipt \
-H "Authorization: Bearer $ZEVARI_API_KEY" \
--data-urlencode "receipt_id=rcpt_..."
- 2. Page through one lead's full history
Call actions.listForLead with lead_id to page cursor-based action history for that lead. Optional cursor, limit (default 50, max 100), from, and to narrow the page and window. Use this to reconstruct everything Zevari has done for a lead without replaying every write endpoint's response. Example: curl -sS -G https://api.zevari.ai/v2/actions/listForLead \
-H "Authorization: Bearer $ZEVARI_API_KEY" \
--data-urlencode "lead_id=lead_..." \
--data-urlencode "limit=50"
- 3. Read receipt state, don't assume success
Receipt state is one of queued, executing, succeeded, failed, deferred, rejected, cancelled, or outcome_unknown. outcome_unknown means the LinkedIn response was lost or unclear; Zevari does not auto-retry it, so treat it as needing manual follow-up rather than a completed send.
- Note 1
Receipts and lead history are scoped to the authenticated user who owns that lead; there is no cross-teammate or cross-organization visibility into another user's receipts or leads, even within the same org.
- Note 2
Prefer this over re-listing inbox, campaign progress, or search results just to confirm a prior write — the receipt and per-lead history are the durable, queryable record.
- Note 3
These reads are /v2-only. /v1 stays frozen and does not expose receipts or lead history.
Docs Links
- Help Center
Human-facing guide to Zevari skills, workflows, agents, videos, safety, and support.
- Workflow Guide
LinkedIn outreach, content, prospect research, audience analysis, campaign, inbox, and GTM workflows for Claude.
- Prompting Guide
Copy-ready prompts that require AI assistants to read the MCP reference before acting.
- Workspaces and Sender Seats
Human-facing setup guide for free workspaces, payer-account billing, members, funded LinkedIn seats, and sender associations.
- Safety Center
Human-facing guide to Zevari safety guardrails, warm-up, pauses, blocked actions, and recovery state.
- Warm-Up
Human-facing guide to LinkedIn sender warm-up and gradual activity ramping.
- API Playbooks
Ordered REST call flows for developers and AI agents using the Zevari API.
- MoltSets + LinkedIn Workflows
Use MoltSets verified contact data with Zevari's LinkedIn enrichment, campaign, and approval-gated execution layer.
- MCP Reference
Agent-facing tool schemas, capability contracts, examples, gotchas, and recovery guidance.
- API Reference
Public REST API reference powered by the Zevari OpenAPI document.
- MCP Reference JSON
Machine-readable MCP tool reference.
- LLMs Full
AI-readable Zevari documentation bundle.
- Support
Send bug reports, support handoffs, and feature requests.