API Reference

API Reference

Complete reference for all 37 API endpoints. All /api/dashboard/* routes require Clerk authentication. Webhook routes use signature verification.

Authentication

All /api/dashboard/* routes require a valid Clerk session. Webhook routes verify signatures. Demo routes are public. All errors return { "error": "..." }.

Campaigns

GET/api/dashboard/campaigns

List campaigns for the current organization.

Clerk
ParamTypeDefaultDescription
pagenumber1Page number
limitnumber25Items per page (max 100)
statusstringallFilter: draft, active, paused, completed, or all
Response 200
{
  "campaigns": [
    {
      "id": "uuid",
      "name": "Q1 Outreach",
      "status": "draft",
      "channels": ["voice", "telegram"],
      "channelPriority": ["telegram", "voice", "email"],
      "leadCount": 150,
      "createdAt": "2025-01-15T10:00:00Z"
    }
  ],
  "pagination": { "page": 1, "limit": 25, "total": 42, "totalPages": 2 }
}
POST/api/dashboard/campaigns

Create a new campaign. Name is required.

Clerk
Request Body
{
  "name": "Q1 Outreach",
  "scriptId": "uuid (optional)",
  "channels": ["voice", "telegram", "email"],
  "channelPriority": ["telegram", "voice", "email"]
}
GET/api/dashboard/campaigns/[id]

Get a single campaign with lead statistics.

Clerk
PATCH/api/dashboard/campaigns/[id]

Update a campaign. All fields are optional.

Clerk
DELETE/api/dashboard/campaigns/[id]

Delete a campaign.

Clerk
POST/api/dashboard/campaigns/[id]/execute

Execute a campaign -- process all assigned leads through configured channels.

Clerk
Response 200
{
  "success": true,
  "progress": {
    "total": 50,
    "processed": 50,
    "succeeded": 42,
    "failed": 8,
    "results": [
      { "leadId": "uuid", "channel": "telegram", "status": "sent" },
      { "leadId": "uuid", "channel": "voice", "status": "failed", "error": "No answer" }
    ]
  }
}
POST/api/dashboard/campaigns/[id]/start

Set campaign status to active.

Clerk
POST/api/dashboard/campaigns/[id]/pause

Set campaign status to paused.

Clerk
GET/api/dashboard/campaigns/[id]/leads

List leads assigned to a campaign.

Clerk
ParamTypeDefaultDescription
pagenumber1Page number
limitnumber100Items per page
POST/api/dashboard/campaigns/[id]/leads

Assign leads to a campaign.

Clerk
Request Body
{ "leadIds": ["uuid1", "uuid2", "uuid3"] }
DELETE/api/dashboard/campaigns/[id]/leads

Remove leads from a campaign.

Clerk

Leads

GET/api/dashboard/leads

List leads with search and filtering.

Clerk
ParamTypeDefaultDescription
pagenumber1Page number
limitnumber25Items per page (max 100)
searchstring--Search across name, email, phone, company, telegram
statusstringallFilter: new, contacted, qualified, converted, rejected
Response 200
{
  "leads": [
    {
      "id": "uuid",
      "firstName": "John",
      "lastName": "Doe",
      "phone": "+380501234567",
      "email": "john@example.com",
      "telegramUsername": "johndoe",
      "company": "Acme Inc",
      "status": "new"
    }
  ],
  "pagination": { "page": 1, "limit": 25, "total": 500, "totalPages": 20 }
}
POST/api/dashboard/leads

Create a single lead. At least one contact field is required.

Clerk
GET/api/dashboard/leads/[id]

Get a single lead.

Clerk
PATCH/api/dashboard/leads/[id]

Update a lead. All fields are optional.

Clerk
DELETE/api/dashboard/leads/[id]

Delete a lead.

Clerk
POST/api/dashboard/leads/import

Import leads from a CSV file. Rows without contact info are skipped.

Clerk

Request: multipart/form-data with a file field containing a .csv file.

CSV columns: firstName, lastName, phone, email, telegramUsername, company, timezone

Scripts

GET/api/dashboard/scripts

List all scripts for the organization.

Clerk
POST/api/dashboard/scripts

Create a new script. Name is required.

Clerk
Request Body
{
  "name": "Cold Call Script v2",
  "content": "Full script text here...",
  "objectionHandlers": [
    "If they say 'too expensive': Emphasize ROI and offer a trial"
  ]
}
GET/api/dashboard/scripts/[id]

Get a single script.

Clerk
PUT/api/dashboard/scripts/[id]

Update a script. All fields are optional.

Clerk
DELETE/api/dashboard/scripts/[id]

Delete a script.

Clerk

Voice Configuration

GET/api/dashboard/voice

Get the voice configuration for the organization. Creates a default if none exists.

Clerk
Response 200
{
  "id": "uuid",
  "voiceId": "B31Kx7rXmNnYqp1QWHR2",
  "selectedVoices": ["olena"],
  "language": "uk",
  "personality": "professional",
  "speed": 1.0
}
PUT/api/dashboard/voice

Update voice configuration.

Clerk
POST/api/dashboard/voice/sync

Sync current voice config and latest script to the Railway voice agent.

Clerk

Call Logs

GET/api/dashboard/calls

List call logs with pagination.

Clerk
ParamTypeDefaultDescription
pagenumber1Page number
limitnumber50Items per page
GET/api/dashboard/calls/[id]

Get a single call log with full transcript.

Clerk

Phone Numbers

GET/api/dashboard/numbers

List all phone numbers for the organization.

Clerk
POST/api/dashboard/numbers

Purchase a phone number via Twilio.

Clerk
Request Body
{ "phoneNumber": "+14155551234", "label": "Sales Line" }
GET/api/dashboard/numbers/available

Search for available phone numbers to purchase.

Clerk
ParamTypeDefaultDescription
countrystringUSTwo-letter country code
areaCodestring--Area code to filter by
GET/api/dashboard/numbers/[id]

Get a single phone number.

Clerk
PUT/api/dashboard/numbers/[id]

Update a phone number's label or campaign assignment.

Clerk
DELETE/api/dashboard/numbers/[id]

Release a phone number from Twilio and delete from database.

Clerk

Email

POST/api/dashboard/email/send

Send an email to a lead via Resend.

Clerk
Request Body
{
  "leadId": "uuid",
  "subject": "Quick question about your workflow",
  "body": "Hi John, I wanted to reach out...",
  "toEmail": "john@example.com"
}
POST/api/dashboard/email/generate

Generate an AI-written email using OpenRouter (Gemini 2.0 Flash).

Clerk
Request Body
{
  "leadName": "John",
  "companyName": "Acme Inc",
  "scriptId": "uuid (optional)",
  "type": "initial | followup | final"
}
POST/api/dashboard/email/test

Send a test email to the authenticated user's email address.

Clerk
GET/api/dashboard/email/messages

List sent email messages.

Clerk

Telegram

GET/api/dashboard/telegram/accounts

List Telegram accounts assigned to the current organization.

Clerk
Response 200
{
  "accounts": [
    {
      "id": "uuid",
      "phone": "+380501234567",
      "username": "sales_agent_1",
      "status": "active",
      "dailyMessageCount": 15,
      "maxDailyMessages": 30
    }
  ]
}

Billing

POST/api/dashboard/billing/checkout

Create a Stripe checkout session for a subscription plan.

Clerk
Request Body
{ "planId": "starter | growth | enterprise" }
PlanAmount
Starter$40/mo
Growth$99/mo
Enterprise$299/mo
POST/api/dashboard/billing/portal

Create a Stripe billing portal session.

Clerk
GET/api/dashboard/billing/usage

Get current month's usage statistics and plan limits.

Clerk
Response 200
{
  "minutes": 150,
  "telegramMessages": 42,
  "emails": 200,
  "plan": "starter",
  "limits": { "minutes": 500, "telegram": 100, "emails": 500 }
}
POST/api/dashboard/billing/liqpay

Create a LiqPay payment for Ukrainian users (UAH).

Clerk
GET/api/dashboard/billing/payment-methods

Check which payment methods are configured.

Public

Analytics

GET/api/dashboard/analytics

Comprehensive cross-channel analytics for the organization.

Clerk

Returns voice stats, telegram stats, email stats, activity chart (7 days), top 5 campaigns, lead status breakdown, and recent 10 activities.

Channel Configuration

GET/api/dashboard/channels

List all channel configurations for the organization.

Clerk
PUT/api/dashboard/channels

Create or update a channel configuration. Uses upsert on (org_id, channel).

Clerk
Request Body
{
  "channel": "email",
  "config": {
    "fromEmail": "sales@yourdomain.com",
    "fromName": "Sales Team",
    "replyTo": "sales@yourdomain.com"
  }
}

Settings / API Keys

GET/api/dashboard/settings/api-keys

List API keys for the organization (prefix + last4 only).

Clerk
POST/api/dashboard/settings/api-keys

Generate a new API key. Full key is returned ONLY in this response.

Clerk
Response 201
{
  "key": "tp_live_a1b2c3d4e5f6...",
  "id": "uuid",
  "name": "Production Key",
  "prefix": "tp_live_a1b2",
  "last4": "w3x4"
}
DELETE/api/dashboard/settings/api-keys?id=uuid

Delete an API key.

Clerk

Webhooks

POST/api/webhook/stripe

Stripe webhook handler. Processes subscription lifecycle events.

Stripe signature
EventAction
checkout.session.completedActivate subscription, set plan
customer.subscription.updatedUpdate plan; downgrade on cancel
customer.subscription.deletedDowngrade to free plan
invoice.payment_failedLog error (Stripe retries)
POST/api/webhook/liqpay

LiqPay webhook handler. Processes payment callbacks with signature verification.

LiqPay signature

Demo

POST/api/demo/email

Send a demo email from the landing page. Rate limited to one per address per hour.

Public
GET/api/demo/status

Check which channels are currently available/configured.

Public

Error Responses

All endpoints return errors in a consistent format:

Error Format
{ "error": "Description of the error" }
CodeMeaning
400Bad request (validation error)
401Unauthorized (missing or invalid Clerk session)
404Resource not found (or does not belong to this org)
429Rate limited
500Internal server error
502External service error (voice agent, telegram worker)
503Service not configured (missing API keys)