Introduction #

Welcome to the Fastlane Phone Hub API. Use this API to manage contacts, lists, tasks, and automate lead ingestion from any external tool. The API follows REST conventions and returns JSON responses.

Base URL

Base URL

Response Format

All responses are JSON. Successful responses follow this structure:

Success Response
{
  "success": true,
  "data": { ... }
}
Error Response
{
  "success": false,
  "error": "Description of what went wrong"
}

Rate Limits

There are currently no rate limits on the API. This may change in the future.

Authentication #

All API requests require authentication. You can authenticate using an API key passed via a header or query parameter. Generate keys from the Settings page in Fastlane Phone Hub.

🔑 API keys start with the prefix fph_

Header Authentication (recommended)

Header
X-API-Key: fph_your_key_here

Query Parameter Authentication

Query Param
GET /api/v1/lists?api_key=fph_your_key_here

Example Request

cURL
curl BASE_URL/api/v1/lists \
  -H "X-API-Key: fph_your_key_here"

Lists #

Lists organize your contacts into groups. Each contact belongs to exactly one list.

GET /api/v1/lists List all contact lists

Returns all contact lists with their contact counts.

Parameters

No parameters required.

Response 200

cURL
curl BASE_URL/api/v1/lists \
  -H "X-API-Key: fph_your_key_here"
Response
{
  "success": true,
  "data": [
    {
      "id": "list-a1b2c3",
      "name": "Inbound Leads",
      "contact_count": 142,
      "created_at": "2024-01-10T08:30:00Z"
    }
  ],
  "total": 1
}
POST /api/v1/lists Create a new list

Creates a new contact list.

Body Parameters

NameTypeRequiredDescription
namestringrequiredName of the list

Response 201

cURL
curl -X POST BASE_URL/api/v1/lists \
  -H "X-API-Key: fph_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"name": "My List"}'
Response
{
  "success": true,
  "data": {
    "id": "list-d4e5f6",
    "name": "My List",
    "created_at": "2024-01-15T14:20:00Z"
  }
}
GET /api/v1/lists/:id Get list with contacts

Returns a single list including all its contacts.

Path Parameters

NameTypeRequiredDescription
idstringrequiredList ID

Response 200

cURL
curl BASE_URL/api/v1/lists/list-a1b2c3 \
  -H "X-API-Key: fph_your_key_here"
Response
{
  "success": true,
  "data": {
    "id": "list-a1b2c3",
    "name": "Inbound Leads",
    "contacts": [
      {
        "id": "contact-x1y2z3",
        "first_name": "John",
        "last_name": "Doe",
        "phone": "+15551234567"
      }
    ],
    "contact_count": 1
  }
}
DELETE /api/v1/lists/:id Delete a list

Permanently deletes a list and all its contacts.

Path Parameters

NameTypeRequiredDescription
idstringrequiredList ID

Response 200

cURL
curl -X DELETE BASE_URL/api/v1/lists/list-a1b2c3 \
  -H "X-API-Key: fph_your_key_here"
Response
{
  "success": true,
  "data": {
    "message": "List deleted successfully"
  }
}

Contacts #

Contacts represent people in your dialer. Each contact belongs to a list and can have call dispositions, notes, and tasks.

GET /api/v1/contacts Get contacts with filters

Returns a paginated list of contacts. Use query parameters to filter.

Query Parameters

NameTypeDescription
list_idstringoptionalFilter by list ID
searchstringoptionalSearch name, email, company
dispositionstringoptionalFilter by disposition
limitintegeroptionalResults per page (default 50)
offsetintegeroptionalPagination offset

Response 200

cURL
curl "BASE_URL/api/v1/contacts?list_id=list-a1b2c3&limit=10" \
  -H "X-API-Key: fph_your_key_here"
Response
{
  "success": true,
  "data": [
    {
      "id": "contact-x1y2z3",
      "first_name": "John",
      "last_name": "Doe",
      "phone": "+15551234567",
      "email": "john@acme.com",
      "company": "Acme",
      "disposition": "New",
      "source": "LinkedIn",
      "tags": "hot,SaaS",
      "city": "New York"
    }
  ],
  "total": 142,
  "limit": 10,
  "offset": 0
}
POST /api/v1/contacts Create a single contact

Creates a new contact in the specified list.

Body Parameters

NameTypeDescription
list_idstringrequiredTarget list ID
first_namestringoptionalFirst name
last_namestringoptionalLast name
titlestringoptionalJob title
companystringoptionalCompany name
emailstringoptionalEmail address
phonestringoptionalPhone number (E.164)
mobilestringoptionalMobile number (E.164)
timezonestringoptionalIANA timezone
dispositionstringoptionalContact disposition
notesstringoptionalNotes about the contact
sourcestringoptionalLead source (LinkedIn, Instantly, Cold Call, etc.)
tagsstringoptionalComma-separated tags (e.g. "hot,decision-maker")
citystringoptionalContact city
linkedin_company_urlstringoptionalLinkedIn company page URL
whatsappstringoptionalWhatsApp number/username
twitterstringoptionalTwitter/X handle
facebookstringoptionalFacebook username
instagramstringoptionalInstagram username
telegramstringoptionalTelegram username
youtubestringoptionalYouTube channel
icebreakerstringoptionalCustom icebreaker text for outreach

Response 201

cURL
curl -X POST BASE_URL/api/v1/contacts \
  -H "X-API-Key: fph_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "list_id": "list-a1b2c3",
    "first_name": "John",
    "last_name": "Doe",
    "title": "CEO",
    "company": "Acme",
    "email": "john@acme.com",
    "phone": "+15551234567",
    "mobile": "+15551234568",
    "timezone": "America/New_York",
    "disposition": "New",
    "notes": "Met at conference",
    "source": "LinkedIn",
    "tags": "hot,decision-maker,SaaS",
    "city": "New York",
    "whatsapp": "+15551234567",
    "twitter": "@johndoe",
    "icebreaker": "Saw your talk at SaaStr"
  }'
Response
{
  "success": true,
  "data": {
    "id": "contact-n7m8p9",
    "first_name": "John",
    "last_name": "Doe",
    "phone": "+15551234567",
    "created_at": "2024-01-15T14:20:00Z"
  }
}
POST /api/v1/contacts/bulk Bulk create contacts (up to 1000)

Import multiple contacts at once. Maximum 1000 contacts per request.

Body Parameters

NameTypeDescription
list_idstringrequiredTarget list ID
contactsarrayrequiredArray of contact objects

Response 200

cURL
curl -X POST BASE_URL/api/v1/contacts/bulk \
  -H "X-API-Key: fph_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "list_id": "list-a1b2c3",
    "contacts": [
      { "first_name": "John", "last_name": "Doe", "phone": "+15551234567" },
      { "first_name": "Jane", "last_name": "Smith", "phone": "+15559876543" }
    ]
  }'
Response
{
  "success": true,
  "imported": 2,
  "total_submitted": 2,
  "errors": [],
  "ids": ["contact-a1", "contact-b2"]
}
GET /api/v1/contacts/:id Get a single contact

Returns full details of a single contact.

Path Parameters

NameTypeDescription
idstringrequiredContact ID

Response 200

cURL
curl BASE_URL/api/v1/contacts/contact-x1y2z3 \
  -H "X-API-Key: fph_your_key_here"
Response
{
  "success": true,
  "data": {
    "id": "contact-x1y2z3",
    "first_name": "John",
    "last_name": "Doe",
    "title": "CEO",
    "company": "Acme",
    "email": "john@acme.com",
    "phone": "+15551234567",
    "mobile": "+15551234568",
    "timezone": "America/New_York",
    "disposition": "New",
    "notes": "Met at conference",
    "created_at": "2024-01-15T14:20:00Z"
  }
}
PUT /api/v1/contacts/:id Update contact fields

Updates specific fields on a contact. Only include the fields you want to change.

Path Parameters

NameTypeDescription
idstringrequiredContact ID

Body Parameters

Any contact field can be updated. Only include fields to change.

Response 200

cURL
curl -X PUT BASE_URL/api/v1/contacts/contact-x1y2z3 \
  -H "X-API-Key: fph_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"disposition": "Interested", "notes": "Wants a demo next week"}'
Response
{
  "success": true,
  "data": {
    "id": "contact-x1y2z3",
    "disposition": "Interested",
    "notes": "Wants a demo next week",
    "updated_at": "2024-01-16T09:00:00Z"
  }
}
DELETE /api/v1/contacts/:id Soft delete a contact

Soft deletes a contact. The contact is marked as deleted but not permanently removed.

Path Parameters

NameTypeDescription
idstringrequiredContact ID

Response 200

cURL
curl -X DELETE BASE_URL/api/v1/contacts/contact-x1y2z3 \
  -H "X-API-Key: fph_your_key_here"
Response
{
  "success": true,
  "data": {
    "message": "Contact deleted successfully"
  }
}
GET /api/v1/contacts/lookup/:phone Lookup by phone number

Find a contact by their phone number. Useful for caller ID lookups.

Path Parameters

NameTypeDescription
phonestringrequiredPhone number (E.164 format)

Response 200

cURL
curl BASE_URL/api/v1/contacts/lookup/%2B15551234567 \
  -H "X-API-Key: fph_your_key_here"
Response
{
  "success": true,
  "data": {
    "id": "contact-x1y2z3",
    "first_name": "John",
    "last_name": "Doe",
    "phone": "+15551234567",
    "company": "Acme"
  }
}

Webhook - Lead Ingestion #

Key Endpoint for Automation

This is the most important endpoint for integrating Fastlane Phone Hub with your automation stack. Push leads from any external tool -- n8n, Make.com, Zapier, or any HTTP client.

POST /api/v1/webhook/lead Push a lead from any external tool

Ingest a lead into Fastlane Phone Hub. You can target a list by ID or name. If a list name is provided and doesn't exist, it will be created automatically.

Deduplication: The endpoint checks for duplicate contacts by email and phone within the target list. Returns 409 if a duplicate is found.

Body Parameters

NameTypeDescription
list_idstringone requiredTarget list ID
list_namestringone requiredList name (auto-creates if new)
first_namestringoptionalFirst name
last_namestringoptionalLast name
titlestringoptionalJob title
companystringoptionalCompany name
emailstringoptionalEmail address
phonestringoptionalPhone number
mobilestringoptionalMobile number
timezonestringoptionalIANA timezone
notesstringoptionalNotes

Success 201   Duplicate 409

cURL
curl -X POST BASE_URL/api/v1/webhook/lead \
  -H "X-API-Key: fph_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "list_name": "Inbound Leads",
    "first_name": "Jane",
    "last_name": "Smith",
    "title": "VP Sales",
    "company": "TechCorp",
    "email": "jane@techcorp.com",
    "phone": "+15559876543",
    "timezone": "America/Chicago",
    "notes": "Filled out demo form"
  }'
Response 201
{
  "success": true,
  "data": {
    "id": "contact-w9x8y7",
    "first_name": "Jane",
    "last_name": "Smith",
    "list_id": "list-q1w2e3",
    "created_at": "2024-01-15T16:30:00Z"
  }
}
Response 409 (Duplicate)
{
  "success": false,
  "error": "Duplicate contact found in this list"
}

Tasks (Nurture) #

Tasks help you schedule follow-ups and nurture activities for contacts.

GET /api/v1/tasks Get tasks

Returns tasks filtered by status and time range.

Query Parameters

NameTypeDescription
statusstringoptionalpending, completed, or all
filterstringoptionaltoday, overdue, or this_week
contact_idstringoptionalFilter tasks for a specific contact

Response 200

cURL
curl "BASE_URL/api/v1/tasks?status=pending&filter=today" \
  -H "X-API-Key: fph_your_key_here"
Response
{
  "success": true,
  "data": [
    {
      "id": "task-t1u2v3",
      "contact_id": "contact-x1y2z3",
      "task_type": "call",
      "scheduled_at": "2024-01-15T10:00:00Z",
      "status": "pending",
      "notes": "Follow up on proposal"
    }
  ]
}
POST /api/v1/tasks Create a task

Schedule a new follow-up task for a contact.

Body Parameters

NameTypeDescription
contact_idstringrequiredContact ID
task_typestringrequiredcall, email, or follow_up
scheduled_atstringrequiredISO 8601 datetime
notesstringoptionalTask description

Response 201

cURL
curl -X POST BASE_URL/api/v1/tasks \
  -H "X-API-Key: fph_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "contact_id": "contact-x1y2z3",
    "task_type": "call",
    "scheduled_at": "2024-01-15T10:00:00Z",
    "notes": "Follow up on proposal"
  }'
Response
{
  "success": true,
  "data": {
    "id": "task-n4m5p6",
    "contact_id": "contact-x1y2z3",
    "task_type": "call",
    "scheduled_at": "2024-01-15T10:00:00Z",
    "status": "pending",
    "created_at": "2024-01-14T18:00:00Z"
  }
}
POST /api/v1/tasks/:id/complete Complete a task

Marks a task as completed.

Path Parameters

NameTypeDescription
idstringrequiredTask ID

Response 200

cURL
curl -X POST BASE_URL/api/v1/tasks/task-t1u2v3/complete \
  -H "X-API-Key: fph_your_key_here"
Response
{
  "success": true,
  "data": {
    "id": "task-t1u2v3",
    "status": "completed",
    "completed_at": "2024-01-15T10:15:00Z"
  }
}
DELETE /api/v1/tasks/:id Delete a task

Permanently deletes a task.

Path Parameters

NameTypeDescription
idstringrequiredTask ID

Response 200

cURL
curl -X DELETE BASE_URL/api/v1/tasks/task-t1u2v3 \
  -H "X-API-Key: fph_your_key_here"
Response
{
  "success": true,
  "data": {
    "message": "Task deleted successfully"
  }
}

SMS #

Send SMS messages directly through the API.

POST /api/v1/sms/send Send an SMS message

Sends an SMS to the specified phone number using your configured Twilio number.

Body Parameters

NameTypeDescription
tostringrequiredRecipient phone number (E.164)
bodystringrequiredMessage text

Response 200

cURL
curl -X POST BASE_URL/api/v1/sms/send \
  -H "X-API-Key: fph_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"to": "+15551234567", "body": "Hello! Following up on our call."}'
Response
{
  "success": true,
  "data": {
    "message_sid": "SM1234567890abcdef",
    "status": "queued"
  }
}

Stats #

Get dashboard statistics for your Fastlane Phone Hub instance.

GET /api/v1/stats Get dashboard stats

Returns high-level metrics for your account.

Parameters

No parameters required.

Response 200

cURL
curl BASE_URL/api/v1/stats \
  -H "X-API-Key: fph_your_key_here"
Response
{
  "success": true,
  "data": {
    "meetings_booked": 24,
    "calls_today": 47,
    "calls_total": 1893,
    "total_contacts": 542,
    "total_lists": 8
  }
}

ABM / Ad Audiences #

Push your contact lists as custom audiences on Meta Ads, LinkedIn Ads, Google Ads, and Reddit Ads for Account-Based Marketing retargeting. All contact data (emails, phones) is hashed with SHA-256 before being sent to the ad platforms.

Note: These endpoints are internal (no API key required) and used by the Fastlane Phone Hub UI. Configure your ad platform credentials in Settings before using these endpoints.
GET /api/abm/platforms Get connection status for all ad platforms

Returns connection status for Meta, LinkedIn, Google Ads, and Reddit Ads. Each platform is verified by pinging its respective API.

Response 200

Response
{
  "success": true,
  "platforms": {
    "meta": {
      "configured": true,
      "connected": true,
      "account_name": "Vision Media",
      "account_id": "act_989273728978435"
    },
    "linkedin": {
      "configured": false,
      "connected": false
    },
    "google": {
      "configured": true,
      "connected": true
    },
    "reddit": {
      "configured": true,
      "connected": true,
      "name": "Reddit Ads",
      "audienceCount": 1
    }
  }
}
POST /api/abm/test/:platform Test connection for a specific platform

Tests the connection to a specific ad platform. Platform must be meta, linkedin, google, or reddit.

URL Parameters

ParamTypeDescription
platformstringPlatform to test: meta, linkedin, google, or reddit

Response 200

cURL
curl -X POST BASE_URL/api/abm/test/meta
Response
{
  "success": true,
  "details": {
    "name": "Vision Media",
    "status": 1
  }
}
GET /api/abm/audiences List all synced audiences

Returns all audiences that have been pushed to ad platforms, with their status, match counts, and source list info.

Response 200

Response
{
  "success": true,
  "audiences": [
    {
      "id": 1,
      "name": "Q1 Prospects",
      "platform": "meta",
      "platform_audience_id": "23850123456789",
      "list_id": "42",
      "list_name": "Sales Pipeline Q1",
      "contact_count": 250,
      "matched_count": 180,
      "status": "ready",
      "last_synced_at": "2026-02-15T19:00:00Z",
      "created_at": "2026-02-15T18:30:00Z"
    }
  ]
}
POST /api/abm/audiences Create audience and push contacts

Creates a custom audience on the specified ad platform and uploads all contacts from the given list. Emails and phones are SHA-256 hashed before upload. Meta supports batches of 10,000 users, Reddit supports batches of 2,500 users per request.

Body Parameters

FieldTypeRequiredDescription
namestringYesAudience name (shown on the ad platform)
platformstringYesmeta, linkedin, or google
list_idstringYesContact list ID to push

Response 200

cURL
curl -X POST BASE_URL/api/abm/audiences \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Q1 Prospects",
    "platform": "meta",
    "list_id": "42"
  }'
Response
{
  "success": true,
  "audience": {
    "id": 1,
    "name": "Q1 Prospects",
    "platform": "meta",
    "platform_audience_id": "23850123456789",
    "contact_count": 250,
    "status": "processing"
  }
}
GET /api/abm/audiences/:id/status Refresh audience status from platform

Queries the ad platform API to get the latest audience status, match count, and sync time. Updates the local database.

Response 200

Response
{
  "success": true,
  "audience": {
    "id": 1,
    "status": "ready",
    "matched_count": 180,
    "last_synced_at": "2026-02-15T19:47:00Z"
  }
}
PUT /api/abm/audiences/:id/sync Re-sync contacts to existing audience

Re-uploads all contacts from the source list to the existing audience on the ad platform. Useful when new contacts have been added to the list.

Response 200

cURL
curl -X PUT BASE_URL/api/abm/audiences/1/sync
DELETE /api/abm/audiences/:id Delete audience from platform and local DB

Deletes the custom audience from the ad platform (Meta/LinkedIn/Google) and marks it as deleted in the local database.

Response 200

cURL
curl -X DELETE BASE_URL/api/abm/audiences/1
GET /api/abm/campaign-stats Get campaign performance metrics from all ad platforms

Fetches campaign performance metrics (impressions, clicks, spend, reach, CTR) from all connected ad platforms (Meta, LinkedIn, Google) for the last 30 days. Each platform is fetched independently; if one fails, others still return data.

Notes:
• Meta uses Graph API v24.0 account-level insights
• Google uses GAQL searchStream for campaign metrics
• LinkedIn uses Ad Analytics API
• Spend is in account currency (typically USD)
• CTR is a percentage (e.g., 2.22 means 2.22%)

Parameters

None

Response 200

cURL
curl BASE_URL/api/abm/campaign-stats
Response
{
  "summary": {
    "impressions": 15420,
    "clicks": 342,
    "spend": 127.50,
    "reach": 12300,
    "ctr": 2.22
  },
  "platforms": {
    "meta": {
      "connected": true,
      "campaigns": [
        {
          "id": "120208...",
          "name": "Retargeting - VP Sales Q1",
          "status": "ACTIVE",
          "impressions": 8200,
          "clicks": 195,
          "spend": 67.30,
          "reach": 6500,
          "ctr": 2.38
        }
      ],
      "totals": { "impressions": 8200, "clicks": 195, "spend": 67.30, "reach": 6500 }
    },
    "linkedin": {
      "connected": true,
      "campaigns": [],
      "totals": { "impressions": 0, "clicks": 0, "spend": 0, "reach": 0 }
    },
    "google": {
      "connected": true,
      "campaigns": [
        {
          "id": "customers/332.../campaigns/123...",
          "name": "Search - Vision Media",
          "status": "ENABLED",
          "impressions": 7220,
          "clicks": 147,
          "spend": 60.20,
          "reach": 5800,
          "ctr": 2.04
        }
      ],
      "totals": { "impressions": 7220, "clicks": 147, "spend": 60.20, "reach": 5800 }
    }
  },
  "date_range": "last_30d",
  "currency": "USD"
}
POST /api/v1/webhook/abm-push Push contacts to ad audiences via webhook

Push one or more contacts to ad platform audiences via API. Contacts are hashed (SHA-256) server-side before being sent to ad platforms. Audiences are auto-created if they don't exist. Perfect for connecting n8n, Make, Zapier, or any external tool.

Authentication: Requires API key via X-API-Key header
Platforms: meta, linkedin, google, reddit
Contacts need: at minimum an email or phone field

Body Parameters

contactsarrayArray of contact objects (or use contact for single)
contactobjectSingle contact: {email, phone, first_name, last_name}
platformsarrayTarget platforms. Default: ["meta"]
audience_namestringAudience name (auto-created if not found)
audience_idnumberPush to existing audience by ID (overrides name)

Response 200

cURL — Single contact
curl -X POST BASE_URL/api/v1/webhook/abm-push \
  -H "Content-Type: application/json" \
  -H "X-API-Key: YOUR_API_KEY" \
  -d '{
    "contact": {
      "email": "john@acme.com",
      "phone": "+15551234567",
      "first_name": "John",
      "last_name": "Doe"
    },
    "platforms": ["meta", "linkedin"],
    "audience_name": "Hot Leads Q1 2026"
  }'
cURL — Batch contacts
curl -X POST BASE_URL/api/v1/webhook/abm-push \
  -H "Content-Type: application/json" \
  -H "X-API-Key: YOUR_API_KEY" \
  -d '{
    "contacts": [
      {"email": "john@acme.com", "first_name": "John"},
      {"email": "jane@corp.io", "phone": "+15559876543"}
    ],
    "platforms": ["meta", "google"],
    "audience_name": "Webinar Attendees"
  }'
Response
{
  "success": true,
  "data": {
    "meta": {
      "success": true,
      "audience_id": 12,
      "audience_name": "Hot Leads Q1 2026",
      "pushed": 2,
      "skipped": 0
    },
    "linkedin": {
      "success": true,
      "audience_id": 13,
      "audience_name": "Hot Leads Q1 2026",
      "pushed": 2,
      "skipped": 0
    }
  }
}
POST /api/v1/webhook/abm-remove Remove contacts from ad audiences via webhook

Remove one or more contacts from ad platform audiences. Use this to stop showing ads to specific contacts (e.g., after they convert or unsubscribe). Supports removing from a specific audience or from ALL audiences on specified platforms.

Body Parameters

contactsarrayArray of contact objects (or contact for single)
audience_idnumberRemove from specific audience
platformsarrayRemove from ALL audiences on these platforms

Response 200

cURL
curl -X POST BASE_URL/api/v1/webhook/abm-remove \
  -H "Content-Type: application/json" \
  -H "X-API-Key: YOUR_API_KEY" \
  -d '{
    "contact": {"email": "john@acme.com"},
    "platforms": ["meta", "linkedin"]
  }'
POST /api/abm/audiences/:id/lookalike Create a lookalike audience from an existing audience

Creates a lookalike/similar audience based on an existing custom audience. Supported on Meta, LinkedIn, and Google. Reddit does not support lookalike audiences.

Body Parameters

countrystringCountry code (default: "US")
rationumberAudience size 0.01 - 0.10 (1% - 10%)
cURL
curl -X POST BASE_URL/api/abm/audiences/5/lookalike \
  -H "Content-Type: application/json" \
  -d '{"country": "US", "ratio": 0.01}'
GET /api/abm/rules List automation rules + CRUD

Manage auto-retargeting rules. When enabled, contacts are automatically pushed to ad audiences based on trigger events (disposition change, new contact added).

Endpoints

GET /api/abm/rulesList all rules
POST /api/abm/rulesCreate rule: {name, trigger_type, trigger_value, platforms, audience_name_template}
PUT /api/abm/rules/:idUpdate rule (enable/disable, change platforms)
DELETE /api/abm/rules/:idDelete rule
GET /api/intent-signals Get unseen intent signals

Returns up to 50 unseen intent signals (email opens, replies, etc.) with contact info. Signals are automatically marked as seen after retrieval. The frontend polls this every 30 seconds to show real-time toast notifications.

GET /api/cadences Cadence orchestration (multi-step sequences)

Create automated multi-step sequences that execute actions over time: push to ad platforms, create nurture tasks, or send Slack notifications. Contacts are enrolled from lists and the processor runs every 60 seconds.

Endpoints

GET /api/cadencesList all cadences with enrollment counts
POST /api/cadencesCreate: {name, steps: [{day_offset, channel, action, message?}]}
PUT /api/cadences/:idUpdate cadence
DELETE /api/cadences/:idDelete cadence (cancels active enrollments)
POST /api/cadences/:id/enrollEnroll contacts: {contact_ids: [...]}
POST /api/cadences/:id/unenrollUnenroll: {contact_id}
Step channels:
ad_retarget — Push to Meta/LinkedIn/Google/Reddit audience
task — Create nurture task (call, email, linkedin_message, follow_up)
notification — Send Slack notification with contact info

CRM #

Manage CRM deals, pipelines, and analytics. Use the webhook endpoint to create deals from external tools like n8n, Make, or Zapier.

POST /api/v1/webhook/crm-deal Create a deal via webhook

Create a CRM deal from an external system. Auto-creates pipelines if needed. Links to existing contacts by email/phone.

Body Parameters

ParamTypeDescription
title *stringDeal title (required)
pipeline_idintegerPipeline ID (or use pipeline_name)
pipeline_namestringPipeline name — auto-creates if not found
stage_idintegerStage ID (or use stage_name)
stage_namestringStage name — fallback to first stage
valuenumberDeal value (default: 0)
currencystringUSD, EUR, GBP (default: USD)
ownerstringDeal owner name
notesstringDeal notes
expected_closedateExpected close date (YYYY-MM-DD)
contact_emailstringLink deal to existing contact by email
contact_phonestringLink deal to existing contact by phone
sourcestringDeal source (LinkedIn, Cold Call, Cold Email, Ads, etc.)

Response 201

cURL
curl -X POST BASE_URL/api/v1/webhook/crm-deal \
  -H "X-API-Key: fph_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Acme Corp Enterprise Deal",
    "pipeline_name": "Sales Pipeline",
    "stage_name": "Qualified",
    "value": 15000,
    "currency": "USD",
    "owner": "John",
    "contact_email": "ceo@acme.com",
    "expected_close": "2026-03-15"
  }'
Response
{
  "success": true,
  "deal": {
    "id": 42,
    "title": "Acme Corp Enterprise Deal",
    "pipeline_id": 1,
    "stage_id": 2,
    "value": 15000,
    "currency": "USD",
    "owner": "John",
    "contact_id": "contact-123"
  }
}
GET /api/crm/deals List deals with pagination and filters

Returns paginated deals with contact and stage info.

Query Parameters

ParamTypeDescription
pipeline_idintegerFilter by pipeline
stage_idintegerFilter by stage
searchstringSearch in title, contact name, company
ownerstringFilter by owner
date_fromdateFilter from date
date_todateFilter to date
pageintegerPage number (default: 1)
limitintegerItems per page (default: 50, max: 200)

Response 200

cURL
curl BASE_URL/api/crm/deals?pipeline_id=1&page=1&limit=20
POST /api/crm/deals Create a deal directly

Create a deal in a specific pipeline and stage.

Body Parameters

ParamTypeDescription
pipeline_id *integerPipeline ID
stage_id *integerStage ID
title *stringDeal title
contact_idstringLink to contact
valuenumberDeal value
currencystringUSD, EUR, GBP
ownerstringDeal owner
notesstringNotes
expected_closedateExpected close date
sourcestringDeal source (LinkedIn, Cold Call, Cold Email, Meta Ads, etc.)

Response 200

cURL
curl -X POST BASE_URL/api/crm/deals \
  -H "Content-Type: application/json" \
  -d '{"pipeline_id":1,"stage_id":1,"title":"New Deal","value":5000,"source":"Cold Call"}'
PUT /api/crm/deals/:id Update a deal (partial update)

Update any deal field. Only provided fields are changed.

Body Parameters

Same as Create Deal (including source) — all fields optional.

Response 200

cURL
curl -X PUT BASE_URL/api/crm/deals/42 \
  -H "Content-Type: application/json" \
  -d '{"value":25000,"owner":"Sarah"}'
PUT /api/crm/deals/:id/stage Move deal to a different stage

Move a deal to a new stage (Kanban drag). Automatically logs the stage change activity and sets closed_at for won/lost stages.

Body Parameters

ParamTypeDescription
stage_id *integerTarget stage ID

Response 200

cURL
curl -X PUT BASE_URL/api/crm/deals/42/stage \
  -H "Content-Type: application/json" \
  -d '{"stage_id":5}'
DELETE /api/crm/deals/:id Delete a deal

Permanently deletes a deal and fires a deal.deleted webhook if configured.

Response 200

cURL
curl -X DELETE BASE_URL/api/crm/deals/42
PUT /api/crm/stages/reorder Reorder Kanban stage columns

Reorder the stages of a pipeline (Kanban column drag & drop). Updates sort_order for each stage.

Body Parameters

ParamTypeDescription
order *arrayArray of stage IDs in desired order

Response 200

cURL
curl -X PUT BASE_URL/api/crm/stages/reorder \
  -H "Content-Type: application/json" \
  -d '{"order":[3,1,2,5,4]}'
GET /api/crm/columns/:pipelineId Get custom columns for a pipeline

Returns custom columns defined for a specific pipeline. Columns have types: text, number, date, url, select.

Response 200

cURL
curl BASE_URL/api/crm/columns/1
Response
[
  {
    "id": 1,
    "pipeline_id": 1,
    "name": "Priority",
    "type": "select",
    "options": "Low, Medium, High",
    "sort_order": 0
  }
]
GET /api/crm/stats/:pipelineId Pipeline analytics and stats

Returns pipeline stats including win rate, deal values, stage breakdown, and period comparison. Supports custom date ranges.

Query Parameters

ParamTypeDescription
date_fromdatePeriod start date (optional, default: this month)
date_todatePeriod end date (optional, default: today)
When date_from/date_to are provided, the previous period is automatically calculated with the same duration for comparison.

Response 200

cURL
curl BASE_URL/api/crm/stats/1?date_from=2026-01-01&date_to=2026-01-31
Response
{
  "totalDeals": 47,
  "totalValue": 125000,
  "wonCount": 12,
  "wonValue": 85000,
  "lostCount": 5,
  "winRate": 71,
  "avgDealValue": 4468.09,
  "avgDaysToClose": 14,
  "dealsThisMonth": 15,
  "valueThisMonth": 45000,
  "dealsLastMonth": 10,
  "valueLastMonth": 30000,
  "periodLabel": "1/1/2026 - 1/31/2026",
  "prevPeriodLabel": "12/1/2025 - 12/31/2025",
  "byStage": [...]
}

ABM Setup Guide #

Step-by-step instructions to configure each ad platform for Account-Based Marketing retargeting.

Meta Ads (Facebook / Instagram)

1. Register as Meta Developer

Go to developers.facebook.com and register your account (free).

2. Create a System User Token (permanent)

  1. Go to Business Settings > System Users
  2. Create a System User with Admin role
  3. Assign your Ad Account to the System User
  4. Generate a token with ads_management + business_management scopes
  5. Select "Never" for token expiration
  6. This token never expires (unless Meta requires a Business Verification)

3. Find your Ad Account ID

In Business Settings > Ad Accounts, copy the act_XXXXXXXXX value.

4. Accept Custom Audiences TOS

Commonly forgotten! Without this step, you'll get a "Permissions error" (error_subcode 1870090) when trying to create Custom Audiences.
  1. Go to Custom Audiences Terms of Service
  2. Replace YOUR_AD_ACCOUNT_ID in the URL with your numeric Ad Account ID (without the act_ prefix)
  3. Accept the Custom Audiences Terms of Service on that page

5. Save in Fastlane

Go to Settings > ABM / Ad Platforms > Meta Ads and paste your Access Token + Ad Account ID.

Google Ads

1. Get your Customer ID

Go to ads.google.com. Your Customer ID is displayed top-right (format: XXX-XXX-XXXX). Remove dashes when saving.

2. Create a Google Cloud Project

  1. Go to console.cloud.google.com
  2. Create a new project
  3. Go to APIs & Services > Library
  4. Search for "Google Ads API" and enable it

3. Create OAuth Credentials

  1. Go to APIs & Services > Credentials
  2. Click "Create Credentials" > "OAuth Client ID"
  3. Select API: Google Ads API, then "User data"
  4. Fill the OAuth consent screen (app name, support email, developer email)
  5. Add scope: Google Ads API (adwords)
  6. Application type: Web application
  7. Add authorized redirect URI: https://developers.google.com/oauthplayground
  8. Copy the Client ID and Client Secret

4. Get a Refresh Token

  1. Go to OAuth 2.0 Playground
  2. Click the gear icon (top-right) > check "Use your own OAuth credentials"
  3. Enter your Client ID and Client Secret
  4. In the left panel, find "Google Ads API" and select the adwords scope
  5. Click "Authorize APIs" and sign in
  6. Click "Exchange authorization code for tokens"
  7. Copy the Refresh Token from the response

5. Get a Developer Token

  1. Create a Google Ads Manager (MCC) account at ads.google.com/home/tools/manager-accounts (free)
  2. In the MCC account, go to Admin > API Center
  3. Copy your Developer Token

6. Save in Fastlane

Go to Settings > ABM / Ad Platforms > Google Ads and fill in all 5 fields: Developer Token, Customer ID, Client ID, Client Secret, Refresh Token.

LinkedIn Ads

1. Create a LinkedIn Developer App

  1. Go to linkedin.com/developers/apps/new
  2. App name: anything (e.g. "Fastlane Phone Hub")
  3. LinkedIn Page: select your Company Page (not a personal profile)
  4. Privacy policy URL: your website privacy page
  5. App logo: upload a square image (min 100px)
  6. Accept terms and create

2. Request Advertising API Access

  1. In your app dashboard, go to the "Products" tab
  2. Find "Advertising API" and click "Request access"
  3. Use case: Direct Advertiser
  4. Intended use: Campaign Management
  5. Description: "We use the API to upload custom audiences for account-based marketing retargeting"
  6. Submit — approval typically takes 24-72 hours (sometimes instant)

3. Configure OAuth Redirect

  1. Once approved, go to your app's "Auth" tab
  2. Add an Authorized redirect URL: https://www.linkedin.com/developers/tools/oauth/redirect
  3. Note your Client ID and Client Secret

4. Generate OAuth Token

  1. Go to LinkedIn OAuth Token Generator
  2. Select your app
  3. Add scopes: r_ads, r_ads_reporting, rw_dmp_segments
  4. Click "Request access token"
  5. Authorize and copy the Access Token

Token expires after 60 days. Set a calendar reminder to regenerate it.

Note: This is a separate token from the li_at cookie used for LinkedIn profile scraping.

5. Save in Fastlane

Go to Settings > ABM / Ad Platforms > LinkedIn Ads and paste your OAuth token. Optionally add your Ad Account ID from Campaign Manager (found in the URL).

Reddit Ads

1. Create a Reddit Ads Account

  1. Go to ads.reddit.com and sign in with your Reddit account
  2. Complete the onboarding: business name, industry, billing info
  3. Once done, you'll see your Ad Account in the dashboard

2. Create a Reddit Developer App (OAuth2)

  1. Go to reddit.com/prefs/apps
  2. Scroll to bottom, click "create another app..."
  3. Name: anything (e.g. "Fastlane Phone Hub")
  4. Type: select "web app"
  5. Redirect URI: https://your-app-url.com/callback (any valid HTTPS URL — you won't actually use it)
  6. Click "create app"
  7. Copy the Client ID (shown under the app name) and Client Secret

3. Get a Refresh Token

  1. Open this URL in your browser (replace YOUR_CLIENT_ID and YOUR_REDIRECT_URI):
https://www.reddit.com/api/v1/authorize?client_id=YOUR_CLIENT_ID&response_type=code&state=fastlane&redirect_uri=YOUR_REDIRECT_URI&duration=permanent&scope=adsread+adsedit
  1. Authorize the app — you'll be redirected to your redirect URI with a code parameter
  2. Copy the code value from the URL bar
  3. Exchange it for a refresh token using curl (or Postman):
cURL — Exchange code for refresh token
curl -X POST https://www.reddit.com/api/v1/access_token \
  -u "YOUR_CLIENT_ID:YOUR_CLIENT_SECRET" \
  -H "User-Agent: FastlanePhoneHub/1.0" \
  -d "grant_type=authorization_code&code=YOUR_CODE&redirect_uri=YOUR_REDIRECT_URI"
  1. Copy the refresh_token from the response (it doesn't expire)

Important: The authorization code is single-use. If the exchange fails, go back to step 1 and get a new code.

4. Find your Ad Account ID

Common mistake! The Ad Account ID is NOT the same as your Reddit user ID or the ID in the ads.reddit.com URL. It has an a2_ prefix.
  1. Your Ad Account ID starts with a2_ (e.g. a2_i6j6fgilbgdm)
  2. To find it, run this curl command with a fresh access token:
cURL — Get access token, then list ad accounts
# Step 1: Get an access token
curl -X POST https://www.reddit.com/api/v1/access_token \
  -u "YOUR_CLIENT_ID:YOUR_CLIENT_SECRET" \
  -H "User-Agent: FastlanePhoneHub/1.0" \
  -d "grant_type=refresh_token&refresh_token=YOUR_REFRESH_TOKEN"

# Step 2: List ad accounts under your business
curl https://ads-api.reddit.com/api/v3/businesses/YOUR_BUSINESS_ID/ad_accounts \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "User-Agent: FastlanePhoneHub/1.0"

# The response contains your Ad Account ID (a2_xxxxx)
  1. Your Business ID is a UUID visible in the Reddit Ads dashboard URL or business settings
  2. The Ad Account ID in the response starts with a2_ — that's the value to use

5. Save in Fastlane

Go to Settings > ABM / Ad Platforms > Reddit Ads and fill in all 4 fields: Client ID, Client Secret, Refresh Token, Ad Account ID (with the a2_ prefix).

Minimum Audience Sizes: Meta requires at least 100 users, LinkedIn requires 300, Google requires 1,000 (for Search), and Reddit requires 1,000. The more contacts with valid emails/phones, the higher your match rate.

Integration Examples #

Complete, copy-paste-ready examples for popular automation platforms and programming languages.

n8n - HTTP Request Node

Use the HTTP Request node in n8n to push leads into Fastlane Phone Hub.

n8n HTTP Request Node Config
// HTTP Request Node Settings:
Method: POST
URL: BASE_URL/api/v1/webhook/lead

// Authentication:
Header Auth:
  Name:  X-API-Key
  Value: fph_your_key_here

// Body (JSON):
{
  "list_name": "n8n Inbound",
  "first_name": "{{ $json.firstName }}",
  "last_name": "{{ $json.lastName }}",
  "email": "{{ $json.email }}",
  "phone": "{{ $json.phone }}",
  "company": "{{ $json.company }}",
  "notes": "Source: n8n automation"
}

Make.com - HTTP Module

Use an HTTP module in Make.com (formerly Integromat) to send leads.

Make.com HTTP Module Config
// Module: HTTP > Make a request
URL:    BASE_URL/api/v1/webhook/lead
Method: POST

// Headers:
X-API-Key:    fph_your_key_here
Content-Type: application/json

// Body type: Raw > JSON
{
  "list_name": "Make.com Leads",
  "first_name": "{{1.firstName}}",
  "last_name": "{{1.lastName}}",
  "email": "{{1.email}}",
  "phone": "{{1.phone}}"
}

Zapier - Webhooks by Zapier

Use the "Webhooks by Zapier" action to POST leads.

Zapier Webhook Action Config
// Action: Webhooks by Zapier > POST
URL: BASE_URL/api/v1/webhook/lead

// Headers:
X-API-Key:    fph_your_key_here
Content-Type: application/json

// Data Pass-Through: JSON
Payload Type: json
Data:
  list_name  = Zapier Leads
  first_name = {{first_name}}
  last_name  = {{last_name}}
  email      = {{email}}
  phone      = {{phone}}

Python

Python (requests)
import requests

API_KEY = "fph_your_key_here"
BASE_URL = "https://your-instance.com"

headers = {
    "X-API-Key": API_KEY,
    "Content-Type": "application/json"
}

# Push a lead
payload = {
    "list_name": "Python Leads",
    "first_name": "Alice",
    "last_name": "Johnson",
    "email": "alice@example.com",
    "phone": "+15551234567"
}

response = requests.post(
    f"{BASE_URL}/api/v1/webhook/lead",
    json=payload,
    headers=headers
)

print(response.status_code)
print(response.json())

JavaScript / Node.js

JavaScript (fetch)
const API_KEY = "fph_your_key_here";
const BASE_URL = "https://your-instance.com";

async function pushLead() {
  const response = await fetch(`${BASE_URL}/api/v1/webhook/lead`, {
    method: "POST",
    headers: {
      "X-API-Key": API_KEY,
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      list_name: "Node.js Leads",
      first_name: "Bob",
      last_name: "Williams",
      email: "bob@example.com",
      phone: "+15559876543"
    })
  });

  const data = await response.json();
  console.log(data);
}

pushLead();

cURL

cURL
# Push a lead via webhook
curl -X POST BASE_URL/api/v1/webhook/lead \
  -H "X-API-Key: fph_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "list_name": "cURL Leads",
    "first_name": "Charlie",
    "last_name": "Brown",
    "email": "charlie@example.com",
    "phone": "+15551112222",
    "company": "Peanuts Inc",
    "title": "Manager",
    "notes": "Imported via cURL"
  }'

# Get all lists
curl BASE_URL/api/v1/lists \
  -H "X-API-Key: fph_your_key_here"

# Get stats
curl BASE_URL/api/v1/stats \
  -H "X-API-Key: fph_your_key_here"

Error Codes #

The API uses standard HTTP status codes. Here is a complete reference of possible responses.

CodeStatusDescription
200 OK Request succeeded. Response body contains the result.
201 Created Resource was successfully created (contacts, lists, tasks).
400 Bad Request Missing required fields or invalid data in the request body.
401 Unauthorized No API key was provided in the request.
403 Forbidden The API key is invalid or has been revoked.
404 Not Found The requested resource (contact, list, task) does not exist.
409 Conflict Duplicate detected. A contact with the same email or phone already exists in the target list.
500 Server Error Something went wrong on the server. Try again or contact support.

Error Response Format

Error Response Example
// 400 - Missing required field
{
  "success": false,
  "error": "list_id is required"
}

// 401 - No API key
{
  "success": false,
  "error": "API key is required. Pass via X-API-Key header or api_key query parameter."
}

// 403 - Invalid key
{
  "success": false,
  "error": "Invalid API key"
}

// 409 - Duplicate
{
  "success": false,
  "error": "Duplicate contact found in this list"
}

Fastlane Phone Hub API Documentation

Built with care. Need help? Contact support.