Programmatic access to OutreachPilot. Import contacts, trigger campaigns, chat with PilotPlus AI, and receive event webhooks. Designed for AI agents and automation platforms.
Master the platform with comprehensive video walkthroughs and step-by-step feature guides.
API access requires a Pro or Scale plan. Go to Settings → Billing.
Go to Settings → Workspace → Developer API. Copy your key — it's shown once.
Send requests with Authorization: Bearer op_live_xxx
All requests require an API key passed as a Bearer token:
curl -H "Authorization: Bearer op_live_YOUR_KEY" \ https://app.outreachpilot.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.
Every response follows a consistent format with machine-readable metadata:
{
"ok": true,
"data": { ... },
"meta": {
"request_id": "req_abc123",
"timestamp": "2026-03-08T...",
"credits_used": 1,
"credits_remaining": 4832
}
}{
"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..."
}
}Import, export, and manage CRM contacts.
/api/v1/contactsscope: contacts · freeList contacts with pagination and filtering.
Query Parameters
limit (max 200), offset, status, folder_id, searchResponse
{ ok: true, data: Contact[], meta: { total, has_more, limit, offset } }Example (cURL)
curl -H "Authorization: Bearer op_live_YOUR_KEY" \ "https://app.outreachpilot.com/api/v1/contacts?limit=50&search=john"
/api/v1/contactsscope: contacts · freeCreate 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://app.outreachpilot.com/api/v1/contacts"/api/v1/contacts/:idscope: contacts · freeGet a single contact by ID.
Response
{ ok: true, data: Contact }Example (cURL)
curl -H "Authorization: Bearer op_live_YOUR_KEY" \ "https://app.outreachpilot.com/api/v1/contacts/CONTACT_UUID"
/api/v1/contacts/:idscope: contacts · freeUpdate 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://app.outreachpilot.com/api/v1/contacts/CONTACT_UUID"/api/v1/contacts/:idscope: contacts · freeDelete a contact permanently.
Response
{ ok: true, data: { deleted: true, id: "..." } }Example (cURL)
curl -X DELETE -H "Authorization: Bearer op_live_YOUR_KEY" \ "https://app.outreachpilot.com/api/v1/contacts/CONTACT_UUID"
Manage companies (Accounts). Contacts are automatically linked to these when domains match.
/api/v1/companiesscope: contacts · freeList companies with pagination and filtering.
Query Parameters
limit (max 200), offset, search, domainResponse
{ ok: true, data: Company[], meta: { total, has_more, limit, offset } }Example (cURL)
curl -H "Authorization: Bearer op_live_YOUR_KEY" \ "https://app.outreachpilot.com/api/v1/companies?domain=acme.com"
/api/v1/companiesscope: contacts · freeCreate 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://app.outreachpilot.com/api/v1/companies"/api/v1/companies/:idscope: contacts · freeGet a single company by ID.
Response
{ ok: true, data: Company }/api/v1/companies/:idscope: contacts · freeUpdate a company. Only provided fields are changed. Custom properties go into context.
Request Body
{ name?, domain?, industry?, size?, ... }Response
{ ok: true, data: Company }/api/v1/companies/:idscope: contacts · freeDelete a company. Linked contacts will have their account_id set to null automatically.
Response
{ ok: true, data: { deleted: true, id: "..." } }Interact with the PilotPlus AI engine. Full tool access: research, draft messages, manage contacts, trigger campaigns.
/api/v1/chatscope: chat · 1 creditSend 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://app.outreachpilot.com/api/v1/chat"Check your credit balance and plan information.
/api/v1/creditsscope: credits · freeGet 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://app.outreachpilot.com/api/v1/credits"
Trigger campaigns and check their status.
/api/v1/campaigns/:id/triggerscope: campaigns · freeAdd 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://app.outreachpilot.com/api/v1/campaigns/CAMPAIGN_UUID/trigger"/api/v1/campaigns/:id/statusscope: campaigns · freeGet 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://app.outreachpilot.com/api/v1/campaigns/CAMPAIGN_UUID/status"
Subscribe to real-time event notifications.
/api/v1/webhooksscope: campaigns · freeList active webhook subscriptions.
Response
{ ok: true, data: { webhooks: [...], available_events: [...] } }/api/v1/webhooksscope: campaigns · freeRegister a webhook URL for events.
Request Body
{ url: "https://...", events: ["email.opened", "campaign.completed"], secret?: "hmac_secret" }Response
{ ok: true, data: WebhookSubscription }/api/v1/webhooks?id=xxxscope: campaigns · freeDeactivate a webhook subscription.
Response
{ ok: true, data: { deleted: true } }All errors include a machine-readable code, message, and details for diagnostics.
| Code | HTTP | When |
|---|---|---|
| MISSING_AUTH | 401 | No Authorization header provided |
| INVALID_API_KEY | 401 | Key not found, revoked, or malformed |
| PLAN_REQUIRED | 403 | Organization not on Pro or Scale plan |
| SCOPE_DENIED | 403 | API key missing required scope for this endpoint |
| ORG_NOT_FOUND | 404 | Organization deleted or invalid |
| RESOURCE_NOT_FOUND | 404 | Contact, campaign, or webhook not found |
| VALIDATION_ERROR | 422 | Invalid request body or missing required fields |
| DUPLICATE_RESOURCE | 409 | Resource already exists (e.g. contact email) |
| INSUFFICIENT_CREDITS | 402 | Not enough credits for the operation |
| CAMPAIGN_NOT_ACTIVE | 400 | Campaign is draft or paused |
| INTERNAL_ERROR | 500 | Unexpected server error |
Rate limiting is managed through credits. Each operation has a credit cost (most are free). AI Chat costs 1-2 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.