API Reference

Programmatic access to OutreachPilot. Import contacts, trigger campaigns, connect native voice agents, chat with PilotPlus AI, and receive event webhooks. Designed for AI agents and automation platforms.

Learning Center

New

Master the platform with comprehensive video walkthroughs and step-by-step feature guides.

Getting Started

Base URL
https://www.useoutreachpilot.com/api/v1

All endpoint paths below are relative to this base URL. The legacy root domain redirects to the same Vercel app, but clients should use the www.useoutreachpilot.com API base directly.

1

Upgrade to Pro

API access requires a Pro or Scale plan. Go to Settings → Billing.

2

Create an API Key

Go to Settings → Workspace → Developer API. New keys include the native scope for voice agents.

3

Make Requests

Send requests with Authorization: Bearer op_live_xxx

Native Voice Bridge

POST /api/v1/native/outreachpilot is the recommended endpoint for low-latency conversational clients, wearables, mobile assistants, and MCP-style agents that already parse user intent into structured actions.

Use executionMode: "fast" for live voice turns. Fast mode targets sub-second server work, returns Server-Timing, and skips read-action audit writes unless requested. Message-send requests follow the same Pilot mode as the dashboard: off blocks, review saves a draft, and auto can send after confirmation.

Every write should include an idempotencyKey. Dangerous writes require a two-step confirmation flow: first call returns mode: "confirmation_required" and pending_action_id; the second call sends confirmed: true to save or execute the confirmed action.

Low-Latency Briefing & Debrief

Voice, wearable, meeting assistant, and agentic clients can use REST endpoints for deterministic sync, or the Native Voice Bridge for sub-second action turns. FramesOS is one supported client pattern, not a separate API surface. Both paths use the same API key format.

NeedREST EndpointNative Action
Contacts listGET /api/v1/contactslookup_person
SignalsGET /api/v1/signalsrecent_signals
Activity historyGET /api/v1/activitylookup_person or reply_inbox
CampaignsGET /api/v1/campaignsadd_to_campaign, pause_campaign, resume_campaign
Campaign statsGET /api/v1/campaigns/:id/statuscampaign_stats
Notes read/createGET/POST /api/v1/notesnote_on_contact

Authentication

All requests require an API key passed as a Bearer token:

curl -H "Authorization: Bearer op_live_YOUR_KEY" \
  https://www.useoutreachpilot.com/api/v1/credits
⚠️

Keep your API key secret. Do not expose it in client-side code or public repositories.

Keys are hashed with SHA-256 and cannot be recovered. If compromised, revoke immediately and create a new one.

Response Format

Every response follows a consistent format with machine-readable metadata:

Success
{
  "ok": true,
  "data": { ... },
  "meta": {
    "request_id": "req_abc123",
    "timestamp": "2026-03-08T...",
    "credits_used": 1,
    "credits_remaining": 4832
  }
}
Error
{
  "ok": false,
  "error": {
    "code": "INVALID_API_KEY",
    "message": "Human-readable message",
    "details": "Diagnostic info...",
    "docs_url": "/docs#invalid_api_key"
  },
  "meta": {
    "request_id": "req_abc123",
    "timestamp": "2026-03-08T..."
  }
}

Contacts

Import, export, and manage CRM contacts.

GET/api/v1/contactsscope: contacts · free

List contacts with pagination and filtering.

Query Parameters

limit (max 200), offset, status, folder_id, search

Response

{ ok: true, data: Contact[], meta: { total, has_more, limit, offset } }

Example (cURL)

curl -H "Authorization: Bearer op_live_YOUR_KEY" \
  "https://www.useoutreachpilot.com/api/v1/contacts?limit=50&search=john"
POST/api/v1/contactsscope: contacts · free

Create one or many contacts. Supports upsert.

Request Body

{ email, first_name?, last_name?, company?, title?, linkedin_url?, upsert?: true } or { contacts: [...], upsert?: true }

Response

{ ok: true, data: { contacts: Contact[], count: number } }

Example (cURL)

curl -X POST -H "Authorization: Bearer op_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"email":"john@acme.com","first_name":"John","company":"Acme"}' \
  "https://www.useoutreachpilot.com/api/v1/contacts"
GET/api/v1/contacts/:idscope: contacts · free

Get a single contact by ID.

Response

{ ok: true, data: Contact }

Example (cURL)

curl -H "Authorization: Bearer op_live_YOUR_KEY" \
  "https://www.useoutreachpilot.com/api/v1/contacts/CONTACT_UUID"
PUT/api/v1/contacts/:idscope: contacts · free

Update a contact. Only provided fields are changed.

Request Body

{ first_name?, last_name?, email?, company?, title?, status?, ... }

Response

{ ok: true, data: Contact }

Example (cURL)

curl -X PUT -H "Authorization: Bearer op_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"title":"VP of Sales"}' \
  "https://www.useoutreachpilot.com/api/v1/contacts/CONTACT_UUID"
DELETE/api/v1/contacts/:idscope: contacts · free

Delete a contact permanently.

Response

{ ok: true, data: { deleted: true, id: "..." } }

Example (cURL)

curl -X DELETE -H "Authorization: Bearer op_live_YOUR_KEY" \
  "https://www.useoutreachpilot.com/api/v1/contacts/CONTACT_UUID"

Companies

Manage companies (Accounts). Contacts are automatically linked to these when domains match.

GET/api/v1/companiesscope: contacts · free

List companies with pagination and filtering.

Query Parameters

limit (max 200), offset, search, domain

Response

{ ok: true, data: Company[], meta: { total, has_more, limit, offset } }

Example (cURL)

curl -H "Authorization: Bearer op_live_YOUR_KEY" \
  "https://www.useoutreachpilot.com/api/v1/companies?domain=acme.com"
POST/api/v1/companiesscope: contacts · free

Create or update companies. Any unrecognized fields are stored in "context".

Request Body

{ name?, domain?, industry?, size?, upsert?: true } or { companies: [...], upsert?: true }

Response

{ ok: true, data: { companies: Company[], count: number } }

Example (cURL)

curl -X POST -H "Authorization: Bearer op_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"Acme Corp","domain":"acme.com","industry":"Software"}' \
  "https://www.useoutreachpilot.com/api/v1/companies"
GET/api/v1/companies/:idscope: contacts · free

Get a single company by ID.

Response

{ ok: true, data: Company }
PUT/api/v1/companies/:idscope: contacts · free

Update a company. Only provided fields are changed. Custom properties go into context.

Request Body

{ name?, domain?, industry?, size?, ... }

Response

{ ok: true, data: Company }
DELETE/api/v1/companies/:idscope: contacts · free

Delete a company. Linked contacts will have their account_id set to null automatically.

Response

{ ok: true, data: { deleted: true, id: "..." } }

AI Chat

Interact with the PilotPlus AI engine. Full tool access: research, draft messages, manage contacts, trigger campaigns.

POST/api/v1/chatscope: chat · 1 credit

Send a message to PilotPlus AI. Non-streaming JSON response. The AI can execute tools (research, drafting, CRM operations) autonomously.

Request Body

{ message: string, thread_id?: string }

Response

{ ok: true, data: { response: string, thread_id: string?, tool_calls: [...], model: string, usage: { input_tokens, output_tokens } } }

Example (cURL)

curl -X POST -H "Authorization: Bearer op_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"message":"Find me 10 VP-level fintech contacts in NYC"}' \
  "https://www.useoutreachpilot.com/api/v1/chat"

Native Voice Bridge

Low-latency command endpoint for voice agents, glasses, and external assistants that need structured access to OutreachPilot.

POST/api/v1/native/outreachpilotscope: native or chat · free

Execute a validated OutreachPilot action. Defaults to fast mode: reads skip extra audit writes, send_message follows the shared Pilot mode (off, review, or auto), and responses include Server-Timing plus performance metadata.

Request Body

{
  "action": {
    "type": "lookup_person",
    "personName": "Sarah Chen",
    "company": "Notion"
  },
  "transcript": "Who is Sarah Chen at Notion?",
  "idempotencyKey": "voice-turn-01",
  "executionMode": "fast",
  "auditReadActions": false
}

Supported action.type values:
lookup_person, lookup_company, recent_signals, start_research, enrich_contact,
add_to_campaign, remove_from_campaign, pause_campaign, resume_campaign,
draft_message, send_message, campaign_stats, reply_inbox, book_meeting,
mark_status, note_on_contact, undo_last.

Irreversible writes return mode="confirmation_required" unless confirmed=true:
send_message, add_to_campaign, remove_from_campaign, pause_campaign,
resume_campaign, book_meeting, and mark_status when status="disqualified".

Response

{
  "ok": true,
  "data": {
    "mode": "result | confirmation_required | queued | duplicate",
    "spoken_summary": "Sarah Chen is VP of Engineering at Notion. Status is qualified.",
    "data": { ... },
    "ids": { "contact_id": "..." },
    "pending_action_id": "...",
    "idempotency_key": "voice-turn-01",
    "audit_id": "...",
    "performance": {
      "execution_mode": "fast",
      "server_elapsed_ms": 42,
      "target_ms": 750,
      "within_target": true
    }
  },
  "meta": { "request_id": "req_abc123", "server_elapsed_ms": 42 }
}

Example (cURL)

curl -X POST -H "Authorization: Bearer op_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"action":{"type":"lookup_person","personName":"Sarah Chen","company":"Notion"},"transcript":"Who is Sarah Chen at Notion?","executionMode":"fast"}' \
  "https://www.useoutreachpilot.com/api/v1/native/outreachpilot"
POST/api/v1/native/outreachpilotscope: native or chat · free

Confirm a pending native action. Use the pending_action_id returned by the first call and send confirmed=true. Reuse the same idempotency key to prevent duplicate writes.

Request Body

{
  "pendingActionId": "PENDING_ACTION_UUID",
  "confirmed": true,
  "idempotencyKey": "voice-turn-02",
  "transcript": "Yes, confirm it.",
  "action": {
    "type": "add_to_campaign",
    "contactRef": "Sarah Chen",
    "campaignRef": "Seed founders"
  }
}

Response

{
  "ok": true,
  "data": {
    "mode": "queued | result | duplicate",
    "spoken_summary": "Sarah Chen is now in Seed founders.",
    "ids": {
      "contact_id": "...",
      "campaign_id": "...",
      "audience_id": "..."
    },
    "idempotency_key": "native:add_to_campaign:..."
  }
}

Credits

Check your credit balance and plan information.

GET/api/v1/creditsscope: credits · free

Get current credit balance, plan tier, and reset date.

Response

{ ok: true, data: { credits_remaining, credits_monthly, plan_tier, credits_reset_at } }

Example (cURL)

curl -H "Authorization: Bearer op_live_YOUR_KEY" \
  "https://www.useoutreachpilot.com/api/v1/credits"

Signals & Activity

Read buying signals, interaction history, and notes for briefing/debrief workflows.

GET/api/v1/signalsscope: contacts or native · free

List recent buying signals. Use this for briefing cards and "what happened since last time" summaries.

Query Parameters

limit (max 100), offset, since, platform, status, contact_id, company, min_intent_score

Response

{ ok: true, data: Signal[], meta: { total, has_more, limit, offset } }

Example (cURL)

curl -H "Authorization: Bearer op_live_YOUR_KEY" \
  "https://www.useoutreachpilot.com/api/v1/signals?since=2026-05-01T00:00:00Z&limit=25"
GET/api/v1/activityscope: contacts or native · free

List interaction history across contacts and campaigns. Notes are included by default.

Query Parameters

limit (max 100), offset, contact_id, campaign_id, direction, channel, since, include_notes=false

Response

{ ok: true, data: Interaction[], meta: { total, has_more, limit, offset } }

Example (cURL)

curl -H "Authorization: Bearer op_live_YOUR_KEY" \
  "https://www.useoutreachpilot.com/api/v1/activity?contact_id=CONTACT_UUID&limit=20"
GET/api/v1/notesscope: contacts or native · free

Read contact notes. Notes are stored as interactions with channel="note".

Query Parameters

limit (max 100), offset, contact_id

Response

{ ok: true, data: Note[], meta: { total, has_more, limit, offset } }

Example (cURL)

curl -H "Authorization: Bearer op_live_YOUR_KEY" \
  "https://www.useoutreachpilot.com/api/v1/notes?contact_id=CONTACT_UUID"
POST/api/v1/notesscope: contacts or native · free

Create a contact note from a debrief.

Request Body

{ contact_id: string, note: string, idempotency_key?: string }

Response

{ ok: true, data: { id, contact_id, content, metadata, created_at } }

Example (cURL)

curl -X POST -H "Authorization: Bearer op_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"contact_id":"CONTACT_UUID","note":"Met after demo. Follow up Friday.","idempotency_key":"debrief-123"}' \
  "https://www.useoutreachpilot.com/api/v1/notes"

Campaigns

List, inspect, update, trigger, and check campaign status.

GET/api/v1/campaignsscope: campaigns · free

List campaigns with pagination and filters.

Query Parameters

limit (max 200), offset, status, type

Response

{ ok: true, data: Campaign[], meta: { total, has_more, limit, offset } }

Example (cURL)

curl -H "Authorization: Bearer op_live_YOUR_KEY" \
  "https://www.useoutreachpilot.com/api/v1/campaigns?status=active&limit=25"
GET/api/v1/campaigns/:idscope: campaigns · free

Get a single campaign including audience_stats.

Response

{ ok: true, data: Campaign & { audience_stats: { total, active, completed, paused, bounced } } }
PATCH/api/v1/campaigns/:idscope: campaigns · free

Update campaign fields such as name, status, type, config, steps, or campaign_mode.

Request Body

{ name?, status?, type?, config?, steps?, campaign_mode? }

Response

{ ok: true, data: Campaign }
POST/api/v1/campaigns/:id/triggerscope: campaigns · free

Add a contact to a campaign. Provide contact_id or contact fields (auto-creates if new).

Request Body

{ contact_id: string } or { email, first_name?, last_name?, company? }

Response

{ ok: true, data: { triggered: true, campaign_id, contact_id } }

Example (cURL)

curl -X POST -H "Authorization: Bearer op_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"email":"john@acme.com","first_name":"John"}' \
  "https://www.useoutreachpilot.com/api/v1/campaigns/CAMPAIGN_UUID/trigger"
GET/api/v1/campaigns/:id/statusscope: campaigns · free

Get campaign status with audience breakdown.

Response

{ ok: true, data: { campaign_id, name, status, audience: { total, active, completed, paused, bounced, failed } } }

Example (cURL)

curl -H "Authorization: Bearer op_live_YOUR_KEY" \
  "https://www.useoutreachpilot.com/api/v1/campaigns/CAMPAIGN_UUID/status"

Webhooks

Subscribe to real-time event notifications.

GET/api/v1/webhooksscope: campaigns · free

List active webhook subscriptions.

Response

{ ok: true, data: { webhooks: [...], available_events: [...] } }
POST/api/v1/webhooksscope: campaigns · free

Register a webhook URL for events.

Request Body

{ url: "https://...", events: ["email.opened", "campaign.completed"], secret?: "hmac_secret" }

Response

{ ok: true, data: WebhookSubscription }
DELETE/api/v1/webhooks?id=xxxscope: campaigns · free

Deactivate a webhook subscription.

Response

{ ok: true, data: { deleted: true } }

Error Codes

All errors include a machine-readable code, message, and details for diagnostics.

CodeHTTPWhen
MISSING_AUTH401No Authorization header provided
INVALID_API_KEY401Key not found, revoked, or malformed
PLAN_REQUIRED403Organization not on Pro or Scale plan
SCOPE_DENIED403API key missing required scope for this endpoint
ORG_NOT_FOUND404Organization deleted or invalid
RESOURCE_NOT_FOUND404Contact, campaign, or webhook not found
VALIDATION_ERROR422Invalid request body or missing required fields
DUPLICATE_RESOURCE409Resource already exists (e.g. contact email)
INSUFFICIENT_CREDITS402Not enough credits for the operation
CAMPAIGN_NOT_ACTIVE400Campaign is draft or paused
INTERNAL_ERROR500Unexpected server error

Rate Limits & Credits

Public API keys are limited to 60 requests per minute per organization. Rate-limited responses return HTTP 429 with X-RateLimit-Remaining and X-RateLimit-Reset headers.

List endpoints use offset pagination with limit, offset, and response metadata: total, has_more, limit, and offset. Contacts, companies, and campaigns allow up to 200 rows per page; signals, activity, and notes allow up to 100.

Credit usage is separate from rate limits. Each operation has a credit cost (most are free). AI Chat costs credits per message depending on the model.

When your credits run out, API calls that require credits will return INSUFFICIENT_CREDITS (402). Check your balance anytime at GET /api/v1/credits.

Credits reset monthly on your billing date. Monitor usage in Settings → Usage.

© 2026 OutreachPilot · Home · Sign In