Skip to main content
All routes below are under your API host (for example https://api.kupe.in) unless noted. Authenticate with Authorization: Bearer <supabase_jwt> from the dashboard, or x-api-key: <kupe_api_key> for server integrations.

Tools — custom HTTP tools and MCP

HTTP tool definitions (CRUD)

Base path: /api/v1/tool-endpoint-defs
MethodPathPurpose
POST""Create a tool definition (URL, schemas, method).
GET""List your tool definitions.
GET/{id}Get one definition.
PUT/{id}Update.
DELETE/{id}Delete.

MCP server tool definitions (CRUD)

Base path: /api/v1/tools-mcp-server-defs Same idea as HTTP tools: POST / GET / GET /{id} / PUT / DELETE for MCP-backed tools.

Attach tools to an agent

Base path: /api/v1/agents
MethodPathPurpose
GET/{agent_id}/toolsList tools linked to the agent.
POST/{agent_id}/toolsAdd tool mappings (body: list of tool config objects).
PATCH/{agent_id}/toolsReplace/update tool configuration.
DELETE/{agent_id}/tools/{tool_id}Remove one tool mapping.
Create tools first (tool-endpoint-defs or tools-mcp-server-defs), then reference their IDs in the agent tools payload when calling POST / PATCH on /{agent_id}/tools.

Post-call analysis — rules and agent mapping

User-scoped rules (CRUD)

Base path: /api/v1/post-analysis
MethodPathPurpose
GET/rulesList rules.
POST/rulesCreate rule (JSON body).
GET/rules/{rule_id}Get one rule.
PUT/rules/{rule_id}Update.
DELETE/rules/{rule_id}Delete.
POST/rules/{rule_id}/duplicateDuplicate.

Map rules to an agent

Base path: /api/v1/agents/{agent_id}
MethodPathPurpose
POST/post-analysisUpsert post-call analysis config for the agent (body includes agent_id aligned with path).
GET/post-analysisGet post-call analysis rows for the agent.
GET/post-analysis/attached-rulesRules attached to the agent.
GET/post-analysis/attached-rule-idsIDs only.
PUT/post-analysis/attached-rulesSet attached rules: body { "rule_ids": ["uuid", ...] }.

Outbound — batch campaigns (end-to-end API)

Base path: /api/v1/batch-call Requires the outbound feature flag on your account. Authenticate with x-api-key or Bearer on every route below (except Twilio /status-callback, which is called by the carrier).

Prerequisites

  1. GET /api/v1/phone — list provisioned lines; note each row’s id (caller_phone_id).
  2. GET /api/v1/agents — note your agent id, or use a workflow id instead.
  3. In the agent system prompt, use variables like {{name}} that match variable_names on the batch.

End-to-end flow

StepMethodPathPurpose
1POST/createCreate batch: agent_id or workflow_id, caller_phone_id, batch_name, variable_names, batch_size.
2aPOST/upload-json/{batch_id}Add targets as JSON (records[] with to_phonenumber + variable keys).
2bPOST/upload/{batch_id}Or upload CSV (multipart/form-data, column to_phonenumber + variables).
2cPOST/{batch_id}/data/upsertOr upsert rows one-by-one / in bulk (items[] with optional id to update).
3GET/{batch_id}/dataVerify recipients (optional ?status=not_started).
4POST/start/{batch_id}Launch campaign — dials up to batch_size numbers at a time.
5GET/{batch_id}/statusPoll batch status + status_counts (not_started, calling, completed, failed, no_answer).
5GET/{batch_id}/dataPoll per-number status and error_message.
Batch-level status: not_startedin_progress (after launch) → completed (all rows terminal). Recipient status: not_startedcallingcompleted | failed | no_answer.

All routes

MethodPathPurpose
POST/createCreate batch (user_id optional — defaults to authenticated user).
GET/meList batches for the authenticated user.
GET/{batch_id}Batch metadata only.
GET/{batch_id}/statusMetadata + aggregated status counts.
GET/{batch_id}/dataAll target numbers (optional ?status=).
POST/{batch_id}/data/upsertInsert/update recipients (before launch).
PATCH/{batch_id}/variablesUpdate variable_names (before launch).
DELETE/{batch_id}/data/{item_id}Remove one recipient (before launch).
POST/upload/{batch_id}CSV upload (to_phonenumber + variable columns).
POST/upload-json/{batch_id}JSON bulk upload.
POST/start/{batch_id}Launch campaign.
DELETE/{batch_id}Delete batch and all recipients.
GET/browsePaginated list (super-admin scoping query params).
GET/user/{user_id}List batches for a user (self or super-admin).
POST/status-callbackTwilio status webhook (internal; no API key).

Example: create → add numbers → launch → poll

export KUPE_API_KEY="your_key"
export BASE="https://api.kupe.in"

# 1. Create batch
BATCH=$(curl -s -X POST "$BASE/api/v1/batch-call/create" \
  -H "x-api-key: $KUPE_API_KEY" -H "Content-Type: application/json" \
  -d '{
    "agent_id": "YOUR_AGENT_UUID",
    "caller_phone_id": "YOUR_PHONE_NUMBER_UUID",
    "batch_name": "API demo",
    "variable_names": ["name"],
    "batch_size": 3
  }' | jq -r '.data.id')

# 2. Add targets
curl -s -X POST "$BASE/api/v1/batch-call/upload-json/$BATCH" \
  -H "x-api-key: $KUPE_API_KEY" -H "Content-Type: application/json" \
  -d '{"records":[{"to_phonenumber":"+919876543210","name":"Ada"}]}'

# 3. Launch
curl -s -X POST "$BASE/api/v1/batch-call/start/$BATCH" \
  -H "x-api-key: $KUPE_API_KEY"

# 4. Poll progress
curl -s "$BASE/api/v1/batch-call/$BATCH/status" -H "x-api-key: $KUPE_API_KEY" | jq .
curl -s "$BASE/api/v1/batch-call/$BATCH/data?status=calling" -H "x-api-key: $KUPE_API_KEY" | jq .
Interactive request/response shapes: Voice Agent API OpenAPI tab → Batch calling (kupe-voice-agent.openapi.yaml).

Call logs — list, pagination, single session, post-call data

Base path: /api/v1/call-analytics
Query / pathBehavior
GET /call-analytics?request_id=<id>Single call by request_id. Response includes session fields; when HIPAA-style, transcript/recording/post-call fields may be stripped.
GET /call-analytics?page=&page_size=Paginated list (server-side). Use filter (alias) for search on request id / call type.
GET /call-analytics (no page)Full list for dashboards (subject to feature flags and scope).
Super-admin scopingOptional query params: scope, organization_ids, owner_user_ids, platform_roles, etc., as supported by your deployment.
Post-call analysis fields (when not redacted) appear on the session object, e.g. post_call_analysis_results and related keys returned by the service layer.

Export (ZIP, optional date range)

GET /call-analytics/export — supports request_id for a single downloadable export, or bulk export with start_date / end_date (YYYY-MM-DD) and email delivery for large ranges.

Billing and usage (usage, cost, credit summary)

Base path: /api/v1/billing Typical read endpoints (also available under /billing/... where the router is mounted without the /api/v1 prefix):
GET pathPurpose
/usage-recordsUsage organized by call sessions.
/usage/recordsService usage records with filters (time_filter, usage_type, search, limit/offset).
/usage/summaryAggregated summary for charts.
/usage/overviewTotals and this-month usage for the authenticated scope.
/usage/sessions/{session_id}Usage and cost for one session.
/usage/exportExport usage (e.g. CSV by email; filters align with /usage/records).
/credit-balanceCredit balance summary — backed by the unified wallets row (available_balance_usd, monthly cap fields when set).
Removed from the product (do not call): self-serve pricing plans, payment checkout, Razorpay webhooks, /balance-history (legacy ledger). Historical balance movements and grants are returned from GET /api/v1/wallets/{wallet_id} (see Wallets below). Other GET /api/v1/billing/** routes your deployment may expose (e.g. forex quotes, service pricing) remain read-only catalog helpers where implemented.

API key vs session (important)

When you authenticate with x-api-key, only GET (and HEAD/OPTIONS) are allowed on /api/v1/billing/**. There is no API-key billing write surface. Wallets and earnings live under /api/v1/wallets/** and /api/v1/earnings/**. Assigning credits, caps, org business model, markup, and commission are POST operations and require a Bearer (session) token with the appropriate org or super-admin role.

Feature flags

Base path: /api/v1/feature-flags
MethodPathPurpose
GET/meBoolean feature flags for the signed-in user.
GET/{user_id}Read another user’s flags when RBAC allows.
PUT/{user_id}Update boolean flags only. Per-user billing markup fields are no longer accepted here — retail markup is configured at the organization via POST /api/v1/orgs/{org_id}/markup (see Wallets).

Wallets (credits, grants, ledger, org business model)

Base path: /api/v1/wallets (plus org-scoped helpers under /api/v1/orgs for business model / commission / markup).
MethodPathPurpose
GET/wallets/meCurrent user’s wallet summary (materialized balance, monthly cap usage when configured).
GET/wallets/{wallet_id}Wallet detail: grants, append-only ledger, upcoming expiry (access controlled by role and org scope).
GET/wallets/usersList user wallets (super_admin).
GET/wallets/orgsList organization wallets (super_admin).
GET/wallets/orgs/{org_id}/membersMember wallets in an organization (org_admin or super_admin).
POST/wallets/{wallet_id}/grantsAssign credits (org admin transfers from org wallet; super admin creates grants as configured).
POST/wallets/{wallet_id}/capSet or clear monthly spend cap (USD) on a wallet.
POST/wallets/{wallet_id}/adjustSuper-admin-only ledger adjustment (no credit-grant row).
POST/orgs/{org_id}/business-modelSet org_type: internal, channel_partner, or distributor (super_admin).
POST/orgs/{org_id}/commissionSet commission percentage for the org (super_admin).
POST/orgs/{org_id}/markupSet markup percentage and currency for reseller pricing (org_admin of reseller org or super_admin).
Legacy organization billing routes such as /organizations/{id}/billing/assign-credits return 410 Gone; use POST /api/v1/wallets/{wallet_id}/grants instead.

Earnings (reseller markup and commission)

Base path: /api/v1/earnings For org_admin users whose organization is a channel_partner or distributor (not internal):
MethodPathPurpose
GET/earnings/meSummary for the caller’s org. Query: period = day | week | month | year | all (default month).
GET/earnings/me/breakdownTime-bucketed breakdown; same period query.
GET/earnings/orgs/{org_id}Super_admin view of any org’s earnings summary; same period query.

API keys — multiple keys, names, revoke

Base path: /api/v1/api-keys
MethodPathPurpose
POST""Create key. Body: { "api_key": "<secret>", "user_id": "<uuid>", , "name": "optional label" }. Response: { "message", "api_key": { ... } }.
GET/fetch/{user_id}List active keys for a user (same user or org-admin scope).
POST/existsBody { user_id, provider_name }true if any active key exists for that provider.
PATCH/{key_id}Body { "name": "new label" } (empty string clears the label).
DELETE/{key_id}Revokes the key (soft revoke); it stops working immediately.
The dashboard API Keys page supports multiple keys, optional names on create, rename, and revoke.

Voice catalog — TTS voices

Base path: /api/v1/tts-voices
MethodPathPurpose
GET""List all TTS voices.
POST""Create a voice row.
GET/{voice_id}Get by id.
GET/provider/{provider_id}List voices for a provider.
Use GET /api/v1/tts-voices (no trailing slash required).
For interactive request/response shapes, continue to use the Voice Agent API OpenAPI tab and kupe-voice-agent.openapi.yaml.