Developer
API Reference
Add leads, manage companies, and create deals programmatically from any server or integration platform.
API Reference
Use the OutboundHQ API to add leads, manage companies, and create deals from your own server, Zapier, Make, or any HTTP client.
Base URL
https://api.outboundhq.ca/api/v1
Authentication
All CRM endpoints require an API key passed in the x-api-key header. Generate one from Dashboard → Team → API Keys.
curl https://api.outboundhq.ca/api/v1/{teamId}/lead-groups \
-H "x-api-key: ohq_your_key_here"app.outboundhq.ca/team/{teamId}/dashboardAPI Keys
API keys are scoped to a single team. The secret is shown once at creation — store it immediately.
Create a key
Requires a logged-in Dashboard session (Firebase auth). Cannot be called with an API key.
POST /{teamId}/api-keys
Authorization: Bearer <firebase-token>
Content-Type: application/json
{ "name": "Zapier Integration" }
// Response 201
{
"key_id": "key_1715000000000_abc12345",
"name": "Zapier Integration",
"secret": "ohq_64hexcharactershere...",
"status": "active",
"createdAt": "2026-05-14T12:00:00.000Z"
}List keys
Returns all keys for the team. The secret is never included.
GET /{teamId}/api-keys
Authorization: Bearer <firebase-token>
// Response 200
{
"api_keys": [
{
"key_id": "key_...",
"name": "Zapier Integration",
"status": "active",
"last_used_at": "2026-05-14T13:00:00.000Z",
"createdAt": "2026-05-14T12:00:00.000Z"
}
]
}Revoke a key
DELETE /{teamId}/api-keys/{keyId}
Authorization: Bearer <firebase-token>
// Response 204 No ContentLeads & Lead Groups
Leads are organised into groups (lists). Every lead belongs to at least one group.
List groups
GET /{teamId}/lead-groups
x-api-key: ohq_your_key
// Response 200
{ "groups": [{ "group_id": "grp_...", "name": "Website Signups", "lead_count": 42 }] }Add a lead to a group
| Field | Type | Required | Notes |
|---|---|---|---|
| string | yes | ||
| firstName | string | no | |
| lastName | string | no | |
| businessName | string | no | Company name |
| phones | array | no | [{ "type": "cell", "number": "+1..." }] |
| jobTitle | string | no | |
| notes | string | no | |
| customFields | object | no | { "key": "value" } |
POST /{teamId}/lead-groups/{groupId}/leads
x-api-key: ohq_your_key
Content-Type: application/json
{
"email": "jane@example.com",
"firstName": "Jane",
"lastName": "Doe",
"businessName": "Acme Corp"
}
// Response 201 — Lead objectBulk import (up to 5,000 leads)
Duplicates matched by email within the team are skipped. This endpoint runs on the long-running handler (timeout: 120 s).
POST https://api.outboundhq.ca/api/v1/{teamId}/lead-groups/{groupId}/leads/import
x-api-key: ohq_your_key
Content-Type: application/json
{
"leads": [
{ "email": "a@example.com", "firstName": "Alice" },
{ "email": "b@example.com", "firstName": "Bob" }
]
}
// Response 200
{ "imported": 2, "skipped": 0 }Update / delete
// Update
PUT /{teamId}/lead-groups/{groupId}/leads/{leadId}
x-api-key: ohq_your_key
Content-Type: application/json
{ "jobTitle": "VP Sales" }
// Remove from group (deletes lead if no other group)
DELETE /{teamId}/lead-groups/{groupId}/leads/{leadId}
// Bulk remove
DELETE /{teamId}/lead-groups/{groupId}/leads
{ "lead_ids": ["lead_aaa", "lead_bbb"] }
// Response: { "deleted": 2 }Companies
Organise leads and deals under a company record.
List companies
GET /{teamId}/companies?limit=25&cursor=...&search=acme
x-api-key: ohq_your_key
// Response 200
{
"companies": [...],
"nextCursor": "base64cursor",
"hasMore": true,
"total": 150
}Create / update a company
| Field | Type | Required | Notes |
|---|---|---|---|
| name | string | yes | |
| industry | string | no | |
| website | string | no | |
| city | string | no | |
| country | string | no | |
| employee_count | number | no | |
| notes | string | no |
// Create
POST /{teamId}/companies
x-api-key: ohq_your_key
{ "name": "Acme Corp", "website": "https://acme.com" }
// Update
PUT /{teamId}/companies/{companyId}
x-api-key: ohq_your_key
{ "industry": "SaaS" }
// Delete (nullifies company_id on leads/deals — does not delete them)
DELETE /{teamId}/companies/{companyId}Bulk import
POST /{teamId}/companies/bulk
x-api-key: ohq_your_key
{ "companies": [{ "name": "Acme Corp" }, { "name": "Beta Inc" }] }
// Response: { "imported": 2, "skipped": 0 }Deals
Track opportunities through a configurable pipeline.
List deals
GET /{teamId}/deals
x-api-key: ohq_your_key
// Response 200
{
"deals": [...],
"pipeline": {
"stages": [{ "id": "stage_prospecting", "name": "Prospecting", "order": 0 }]
}
}Create / update a deal
| Field | Type | Required | Notes |
|---|---|---|---|
| title | string | yes | |
| company_id | string | no | |
| contact_lead_id | string | no | |
| value | number | no | |
| currency | string | no | Default: USD |
| stage | string | no | e.g. stage_prospecting |
| close_date | string | no | ISO 8601 date |
// Create
POST /{teamId}/deals
x-api-key: ohq_your_key
{ "title": "Acme Corp — Enterprise", "value": 12000, "stage": "stage_prospecting" }
// Update (move stage, change value, etc.)
PUT /{teamId}/deals/{dealId}
x-api-key: ohq_your_key
{ "stage": "stage_qualified" }Default pipeline stages
stage_prospectingstage_qualifiedstage_proposalstage_negotiationstage_closed_wonstage_closed_lostCustomise stages via PUT /{teamId}/deal-pipeline.
Campaigns
Create and manage outreach campaigns — including drip email/SMS sequences and social post campaigns — programmatically.
List / get campaigns
// List all campaigns (paginated)
GET /{teamId}/campaigns?limit=20&lastEvaluatedKey=...
x-api-key: ohq_your_key
// Response 200
{
"campaigns": [
{
"campaign_id": "cmp_...",
"name": "Q2 Outreach",
"status": "active",
"drip_enabled": true,
"stats": { "totalLeads": 120 }
}
],
"hasMore": true,
"lastEvaluatedKey": "base64cursor"
}
// Get a single campaign
GET /{teamId}/campaigns/{campaignId}
x-api-key: ohq_your_key
// Response 200 — full campaign objectCreate / update / delete
| Field | Type | Required | Notes |
|---|---|---|---|
| name | string | yes | |
| drip_enabled | boolean | no | true for drip email/SMS sequences |
| seed_lead_group_id | string | no | Lead group ID to attach on creation |
| seed_lead_ids | array | no | Individual lead IDs to enroll on creation |
| existing_lead_group_id | string | no | Use an existing group as the campaign lead group |
| connections | array | no | Connected account IDs for sending |
// Create
POST /{teamId}/campaigns
x-api-key: ohq_your_key
Content-Type: application/json
{ "name": "Q2 Outreach", "drip_enabled": true }
// Response 201
{
"campaign_id": "cmp_...",
"name": "Q2 Outreach",
"status": "draft",
"drip_enabled": true,
"stats": { "totalLeads": 0 }
}
// Update
PUT /{teamId}/campaigns/{campaignId}
x-api-key: ohq_your_key
{ "name": "Q2 Outreach — Revised" }
// Delete
DELETE /{teamId}/campaigns/{campaignId}
// Response 204 No ContentDuplicate a campaign
Creates a new campaign in draft status with all events copied and stats reset. Useful for reusing a sequence template.
POST /{teamId}/campaigns/{campaignId}/duplicate
x-api-key: ohq_your_key
Content-Type: application/json
{ "name": "Q3 Outreach (copy)" }
// Response 201 — new campaign object with status "draft" and zeroed statsStart / pause / resume
A campaign must be in draft or ready status to start. Starting a drip campaign immediately enrolls all leads in the linked groups and begins sending scheduled steps.
// Start — promotes approved/draft events to pending, sets status → active
POST /{teamId}/campaigns/{campaignId}/start
x-api-key: ohq_your_key
// Response 200
{ "success": true, "message": "Campaign started successfully", "status": "active" }
// Pause — halts sending; campaign must be active
POST /{teamId}/campaigns/{campaignId}/pause
x-api-key: ohq_your_key
// Response 200
{ "success": true, "status": "paused" }
// Resume — resumes from where it left off; campaign must be paused
POST /{teamId}/campaigns/{campaignId}/resume
x-api-key: ohq_your_key
// Response 200
{ "success": true, "status": "active" }draftreadyactivepausedgeneratingCampaign leads
Leads within a campaign are separate from CRM lead groups — they carry campaign-specific fields like status and source.
| Field | Type | Required | Notes |
|---|---|---|---|
| string | no | Recommended for outreach campaigns | |
| businessName | string | no | |
| firstName | string | no | |
| lastName | string | no | |
| phones | array | no | [{ "type": "cell", "number": "+1..." }] |
| websiteUrl | string | no | |
| industry | string | no | |
| source | string | no | e.g. manual, import |
| status | string | no | new | contacted | interested | qualified | rejected |
// Add a single lead
POST /{teamId}/campaigns/{campaignId}/leads
x-api-key: ohq_your_key
Content-Type: application/json
{
"email": "jane@acme.com",
"firstName": "Jane",
"businessName": "Acme Corp"
}
// Response 201 — lead object
// List leads (paginated)
GET /{teamId}/campaigns/{campaignId}/leads?limit=50&status=new&lastEvaluatedKey=...
x-api-key: ohq_your_key
// Response 200
{ "leads": [...], "hasMore": true }
// Bulk import (up to 5,000)
POST /{teamId}/campaigns/{campaignId}/import-leads
x-api-key: ohq_your_key
{
"leads": [
{ "email": "a@example.com", "firstName": "Alice" },
{ "email": "b@example.com", "firstName": "Bob" }
]
}
// Response 200
{ "success": true, "imported": 2, "skipped": 0, "errors": [] }
// Update a lead
PUT /{teamId}/campaigns/{campaignId}/leads/{leadId}
x-api-key: ohq_your_key
{ "status": "interested" }
// Delete a lead
DELETE /{teamId}/campaigns/{campaignId}/leads/{leadId}
// Response 204 No ContentCampaign events
Each step in a campaign is an event — an outreach message or social post scheduled for a specific time (or, for drip campaigns, a day offset). Events have a status lifecycle of their own.
| Field | Type | Required | Notes |
|---|---|---|---|
| event_data | object | yes | outreach or social_media payload (see below) |
| scheduledFor | string | no | ISO 8601 timestamp — required for non-drip events |
| is_drip_template | boolean | no | true for drip sequence steps |
| delay_days | number | no | Days after enrollment to send (drip only); must be unique per campaign |
| status | string | no | draft | review | pending | approved | rejected |
// List events for a campaign
GET /{teamId}/campaigns/{campaignId}/events
x-api-key: ohq_your_key
// Response 200
{ "events": [...] }
// Create an outreach event (scheduled)
POST /{teamId}/campaigns/{campaignId}/events
x-api-key: ohq_your_key
Content-Type: application/json
{
"scheduledFor": "2026-06-10T10:00:00Z",
"event_data": {
"outreach": {
"channel": "email",
"from_email": "you@yourco.com",
"subject": "Quick intro, {{firstName}}",
"body": "Hi {{firstName}}, I wanted to reach out..."
}
}
}
// Update an event (e.g. reschedule or edit content)
PUT /{teamId}/campaigns/{campaignId}/events/{eventId}
x-api-key: ohq_your_key
{ "scheduledFor": "2026-06-11T10:00:00Z" }
// Delete an event
DELETE /{teamId}/campaigns/{campaignId}/events/{eventId}
// Response 204 No Contentdraftreviewpendingapprovedrejectedpostedcompletedfaileddelay_days values within the same campaign.Attachments
Email outreach events and campaigns support file attachments (PDF, images, Office documents, etc.). The aggregate size of all attachments plus the email body must be under 10 MB. Executable file types are blocked. Uploading follows a two-step presigned-URL pattern: request an upload URL → PUT the file to S3 → register the s3_key with the backend.
Per-event attachments
// Step 1 — request a presigned upload URL
POST /{teamId}/campaigns/{campaignId}/events/{eventId}/attachments/upload
x-api-key: ohq_your_key
Content-Type: application/json
{ "fileName": "brochure.pdf", "contentType": "application/pdf", "size": 524288 }
// Response 200
{
"presignedUrl": "https://s3.amazonaws.com/...",
"s3_key": "attachments/team_.../brochure-uuid.pdf"
}
// Step 2 — upload the file directly to S3
PUT <presignedUrl>
Content-Type: application/pdf
<file bytes>
// Step 3 — register the uploaded file on the event
POST /{teamId}/campaigns/{campaignId}/events/{eventId}/attachments
x-api-key: ohq_your_key
{ "s3_key": "attachments/...", "fileName": "brochure.pdf", "contentType": "application/pdf", "size": 524288 }
// Response 200
{ "success": true, "attachments": [{ "s3_key": "...", "fileName": "brochure.pdf", "contentType": "application/pdf", "size": 524288, "signedUrl": "https://..." }] }
// Delete an attachment by index
DELETE /{teamId}/campaigns/{campaignId}/events/{eventId}/attachments/{index}
x-api-key: ohq_your_key
// Response 200 — updated attachments arrayCampaign-level attachments
Campaign-level attachments are appended to every email step in the campaign.
// Step 1 — presigned upload URL
POST /{teamId}/campaigns/{campaignId}/attachments/upload
x-api-key: ohq_your_key
{ "fileName": "one-pager.pdf", "contentType": "application/pdf", "size": 204800 }
// Step 2 — PUT file to S3 (same as above)
// Step 3 — register
POST /{teamId}/campaigns/{campaignId}/attachments
x-api-key: ohq_your_key
{ "s3_key": "...", "fileName": "one-pager.pdf", "contentType": "application/pdf", "size": 204800 }
// Delete by index
DELETE /{teamId}/campaigns/{campaignId}/attachments/{index}
x-api-key: ohq_your_keysignedUrl values returned by GET endpoints expire after 1 hour and are regenerated fresh on every request — never store them; always re-fetch the campaign or event to get a valid URL.Drip sequences (manual setup)
A drip sequence is built from events with is_drip_template: true and a delay_days offset. Leads enrolled after the campaign starts automatically receive each step at the right interval. Supports {{firstName}}, {{lastName}}, {{businessName}}, and {{email}} template variables.
drip_enabled: true, seed_lead_group_id: "grp_...") → add drip-template events → start campaign. The campaign auto-creates a single lead group; new leads added to that group are automatically enrolled.// 1. Create the campaign
POST /{teamId}/campaigns
x-api-key: ohq_your_key
{ "name": "Q2 Drip", "drip_enabled": true }
// 2. Add step — Day 0 intro email
POST /{teamId}/campaigns/{campaignId}/events
x-api-key: ohq_your_key
{
"is_drip_template": true,
"delay_days": 0,
"event_data": {
"outreach": {
"channel": "email",
"from_email": "you@yourco.com",
"subject": "Quick intro, {{firstName}}",
"body": "Hi {{firstName}},\n\nI wanted to reach out about {{businessName}}..."
}
}
}
// 3. Add step — Day 3 follow-up email
POST /{teamId}/campaigns/{campaignId}/events
x-api-key: ohq_your_key
{
"is_drip_template": true,
"delay_days": 3,
"event_data": {
"outreach": {
"channel": "email",
"from_email": "you@yourco.com",
"subject": "Following up, {{firstName}}",
"body": "Just checking in — did my last note reach you?"
}
}
}
// 4. Add step — Day 7 SMS nudge
POST /{teamId}/campaigns/{campaignId}/events
x-api-key: ohq_your_key
{
"is_drip_template": true,
"delay_days": 7,
"event_data": {
"outreach": {
"channel": "sms",
"from_phone": "+15550001234",
"body": "Hi {{firstName}}, happy to chat about {{businessName}} — just reply here."
}
}
}
// 5. Start — lead group was already set at creation
POST /{teamId}/campaigns/{campaignId}/start
x-api-key: ohq_your_keyAI generation
Skip manual event creation and let OutboundHQ's AI write and schedule your entire sequence or social content plan in one call.
Generate an outreach sequence
Pass a prompt describing your goal and OutboundHQ creates all drip steps (subject lines, body copy, timing) automatically.
| Field | Type | Required | Notes |
|---|---|---|---|
| contentPrompt | string | yes | Describe the campaign goal and tone |
| channels | array | yes | ["email"] or ["email","sms"] |
| frequencyPrompt | string | no | e.g. "3 emails over 2 weeks, then weekly" |
| fromEmail | string | no | |
| fromPhone | string | no | |
| isDripCampaign | boolean | no | Creates drip-template events when true |
| useHtmlEmail | boolean | no | Generates rich HTML emails (async) |
POST /{teamId}/campaigns/{campaignId}/generate-outreach-sequence
x-api-key: ohq_your_key
Content-Type: application/json
{
"contentPrompt": "Introduce our SaaS product to SMB owners, highlight ROI, and invite a demo",
"frequencyPrompt": "3 emails — day 0, day 4, day 10 — then an SMS on day 14",
"channels": ["email", "sms"],
"fromEmail": "you@yourco.com",
"fromPhone": "+15550001234",
"isDripCampaign": true
}
// Response 200 (plaintext, sync)
{ "success": true, "sequenceSteps": 4, "eventsCreated": 4 }
// Response 200 (HTML email, async — events created in background)
{ "success": true, "sequenceSteps": 4, "async": true }Generate social media posts
Generates a full content plan and queues individual post-writing tasks. The campaign status changes to generating while tasks run; posts appear as events when ready.
| Field | Type | Required | Notes |
|---|---|---|---|
| prompt | string | yes | Topic, tone, and goal for the content |
| numberOfPosts | number | yes | |
| platforms | array | yes | ["instagram","tiktok","reddit", ...] |
| presets | object | no | Reddit: [{ "subreddit": "...", "kind": "self" }] |
| brandingAssetIds | array | no | Brand asset IDs to include |
POST /{teamId}/campaigns/{campaignId}/generate-social-posts
x-api-key: ohq_your_key
Content-Type: application/json
{
"prompt": "Promote our new feature launch with engaging, conversational posts",
"numberOfPosts": 6,
"platforms": ["instagram", "tiktok"],
"brandingAssetIds": ["asset_abc"]
}
// Response 200
{
"success": true,
"message": "Post generation in progress",
"tasksQueued": 6,
"tasksFailed": 0,
"campaignId": "cmp_...",
"status": "generating"
}GET /{teamId}/campaigns/{campaignId} until status leaves generating, then fetch events to see the generated posts.Contact Form Intake
A public endpoint — no API key required. Accepts HTML form submissions and creates leads automatically. Configure field mapping and auto-reply in Inbox → Auto-Reply → Contact Form.
Intake endpoint
POST https://api.outboundhq.ca/api/v1/intake/{teamId}/contact
Content-Type: application/json (or application/x-www-form-urlencoded)
{
"email": "jane@example.com",
"firstName": "Jane",
"message": "I'd love a demo."
}
// Response 200
{ "success": true }_hp field as a honeypot — submissions where it's filled are silently dropped as bot traffic.HTML form example
<form action="https://api.outboundhq.ca/api/v1/intake/YOUR_TEAM_ID/contact" method="POST"> <input type="text" name="firstName" placeholder="First name"> <input type="email" name="email" placeholder="Email" required> <textarea name="message" placeholder="Message"></textarea> <input type="text" name="_hp" style="display:none" tabindex="-1" autocomplete="off"> <button type="submit">Send</button> </form>
Auto-reply emails support template variables: {{firstName}}, {{email}}, {{company}}.
MCP — Use OutboundHQ from any AI assistant
The OutboundHQ MCP server lets AI assistants like Claude and Cursor add leads, create deals, and manage companies on your behalf — just by asking in plain English.
What is MCP?
The Model Context Protocol is an open standard that lets AI assistants call external tools. You run a small server process; the AI talks to it over stdin/stdout and decides which tools to call based on what you ask. No copy-pasting, no manual API calls.
↓ AI picks tool
MCP server: add_lead_to_group(group_id, email, ...)
↓ HTTP call
OutboundHQ API: 201 Created ✓
Install & configure
The MCP server is published on npm as outboundhq-mcp. You need Node.js 18+ and an API key — no cloning required.
Go to Dashboard → Team → API Keys, create a key, and copy the secret.
Find your Team ID in the dashboard URL: /team/YOUR_TEAM_ID/dashboard
Pick your assistant below and paste in your key and team ID — npx will download and run the server automatically.
Claude Code
Browser login Recommended
One command — a browser opens, you log in, and Claude Code is connected. No API key or team ID needed.
claude mcp add outboundhq -- npx mcp-remote https://api.outboundhq.ca/mcp
API key (manual)
If you prefer to use an API key directly, run this instead:
claude mcp add outboundhq \ -e OUTBOUNDHQ_API_KEY=ohq_your_secret_here \ -e OUTBOUNDHQ_TEAM_ID=your_team_id_here \ -- npx outboundhq-mcp
Claude Desktop
Open claude_desktop_config.json — on Mac it's at ~/Library/Application Support/Claude/, on Windows %APPDATA%\Claude\ — and add:
{
"mcpServers": {
"outboundhq": {
"command": "npx",
"args": ["outboundhq-mcp"],
"env": {
"OUTBOUNDHQ_API_KEY": "ohq_your_secret_here",
"OUTBOUNDHQ_TEAM_ID": "your_team_id_here"
}
}
}
}Restart Claude Desktop. You'll see "outboundhq" appear in the MCP tools list.
Cursor
Add to ~/.cursor/mcp.json (create it if it doesn't exist):
{
"mcpServers": {
"outboundhq": {
"command": "npx",
"args": ["outboundhq-mcp"],
"env": {
"OUTBOUNDHQ_API_KEY": "ohq_your_secret_here",
"OUTBOUNDHQ_TEAM_ID": "your_team_id_here"
}
}
}
}Available tools
Once connected, you can ask naturally. The AI picks the right tool:
| Tool | What it does | Example prompt |
|---|---|---|
| list_lead_groups | List all groups with IDs and counts | "What lead groups do I have?" |
| add_lead_to_group | Add one lead to a group | "Add sarah@acme.com to the Inbound group" |
| import_leads_to_group | Bulk-import up to 200 leads per call | "Import these 20 leads into Webinar Signups" |
| list_companies | List companies with optional search | "Show me all companies in the SaaS industry" |
| create_company | Create a new company record | "Create a company called Acme Corp" |
| list_deals | List deals, optionally filtered by stage | "What deals are in Prospecting?" |
| create_deal | Create a new deal | "Create a deal — Acme Corp Enterprise, $50k, Prospecting" |
| update_deal | Update fields on an existing deal | "Move the Acme deal to Qualified" |
| list_campaigns | List all campaigns | "Show me my active campaigns" |
| create_campaign | Create a new campaign | "Create a drip campaign called Q3 Outreach" |
| update_campaign | Rename or attach lead groups | "Attach the Inbound group to my Q3 campaign" |
| start_campaign | Start a draft or ready campaign | "Start the Q3 Outreach campaign" |
| pause_campaign | Pause an active campaign | "Pause Q3 Outreach" |
| resume_campaign | Resume a paused campaign | "Resume Q3 Outreach" |
| add_campaign_recipient | Add a recipient directly to a campaign | "Add john@acme.com to Q3 Outreach" |
| import_campaign_recipients | Bulk-import up to 200 campaign recipients per call | "Import these leads into Q3 Outreach" |
| add_drip_step | Add a timed email or SMS drip step | "Add a day-3 follow-up email to Q3 Outreach" |
| list_social_accounts | List connected social accounts with accountIds | "What social accounts do I have connected?" |
| connect_social_account | Get an OAuth URL to connect a social platform | "Give me the link to connect my Reddit account" |
| create_campaign_post | Create a social media post in a campaign | "Post to r/SaaS about our new feature launch" |
| list_assets | List asset summaries and processing status | "Which uploaded assets are ready?" |
| get_asset_upload_url | Create a signed direct-to-storage upload | "Give me a signed upload URL for interview.mp4" |
| inspect_asset | Page or search an asset's transcript and scene metadata | "Find scenes mentioning the product launch" |
Claude skill instructions
Want Claude to manage your CRM directly from the terminal? Create a slash command by saving the text below as .claude/commands/crm.md in your project. Once saved, type /crm in Claude Code and describe what you want — Claude will authenticate with your API key, resolve group IDs, confirm before bulk actions, and make the API calls for you directly.
# .claude/commands/crm.md
# Save this file, then use /crm in Claude Code to manage your OutboundHQ CRM.
## Credentials
Base URL: https://api.outboundhq.ca/api/v1
Auth: x-api-key header on every request
If $OUTBOUNDHQ_API_KEY or $OUTBOUNDHQ_TEAM_ID are not set, ask the user before
proceeding. Get a key from Dashboard → Team → API Keys. Find the team ID in the
dashboard URL: /team/{teamId}/dashboard
## Before you do anything
Fetch all lead groups so you can resolve names to IDs:
curl -s https://api.outboundhq.ca/api/v1/$OUTBOUNDHQ_TEAM_ID/lead-groups \
-H "x-api-key: $OUTBOUNDHQ_API_KEY"
Never guess a group_id — always resolve it first.
## Adding a single lead
Extract: email (required), firstName, lastName, businessName, phone, jobTitle, notes.
Ask which group only if the user hasn't said.
curl -s -X POST https://api.outboundhq.ca/api/v1/$OUTBOUNDHQ_TEAM_ID/lead-groups/{groupId}/leads \
-H "x-api-key: $OUTBOUNDHQ_API_KEY" \
-H "Content-Type: application/json" \
-d '{"email":"jane@example.com","firstName":"Jane","lastName":"Doe"}'
Confirm: "Added [name] to [group name]."
## Importing multiple leads (up to 5,000 per call)
Parse all entries the user provides (table, CSV, JSON, plain list).
Confirm count and group first: "I'll import 12 leads into 'Webinar Signups'. Go ahead?"
curl -s -X POST https://api.outboundhq.ca/api/v1/$OUTBOUNDHQ_TEAM_ID/lead-groups/{groupId}/leads/import \
-H "x-api-key: $OUTBOUNDHQ_API_KEY" \
-H "Content-Type: application/json" \
-d '{"leads":[{"email":"a@example.com"},{"email":"b@example.com"}]}'
Report: "Imported 12. 0 skipped (duplicates)."
## Adding a company
Extract: name (required), industry, website, city, country, employee_count, notes.
curl -s -X POST https://api.outboundhq.ca/api/v1/$OUTBOUNDHQ_TEAM_ID/companies \
-H "x-api-key: $OUTBOUNDHQ_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"Acme Corp","website":"https://acme.com"}'
## Adding or updating a deal
Extract: title (required), value, currency, stage, company_id, contact_lead_id, close_date.
Stage IDs: stage_prospecting stage_qualified stage_proposal
stage_negotiation stage_closed_won stage_closed_lost
Map stage names to IDs automatically.
# Create
curl -s -X POST https://api.outboundhq.ca/api/v1/$OUTBOUNDHQ_TEAM_ID/deals \
-H "x-api-key: $OUTBOUNDHQ_API_KEY" \
-H "Content-Type: application/json" \
-d '{"title":"Acme Enterprise","value":12000,"stage":"stage_prospecting"}'
# Update — fetch deals first to find deal_id
curl -s https://api.outboundhq.ca/api/v1/$OUTBOUNDHQ_TEAM_ID/deals \
-H "x-api-key: $OUTBOUNDHQ_API_KEY"
curl -s -X PUT https://api.outboundhq.ca/api/v1/$OUTBOUNDHQ_TEAM_ID/deals/{dealId} \
-H "x-api-key: $OUTBOUNDHQ_API_KEY" \
-H "Content-Type: application/json" \
-d '{"stage":"stage_qualified"}'
## Listing / searching
# Lead groups
curl -s https://api.outboundhq.ca/api/v1/$OUTBOUNDHQ_TEAM_ID/lead-groups \
-H "x-api-key: $OUTBOUNDHQ_API_KEY"
# Companies (optional ?search=acme)
curl -s "https://api.outboundhq.ca/api/v1/$OUTBOUNDHQ_TEAM_ID/companies?search=acme" \
-H "x-api-key: $OUTBOUNDHQ_API_KEY"
# Deals
curl -s https://api.outboundhq.ca/api/v1/$OUTBOUNDHQ_TEAM_ID/deals \
-H "x-api-key: $OUTBOUNDHQ_API_KEY"
Present results as compact tables.
## Tone
Be direct and fast. Confirm actions in one sentence.OUTBOUNDHQ_API_KEY and OUTBOUNDHQ_TEAM_ID as environment variables so Claude never needs to ask for them.