Developer docs

Connected Push API

One API for structured and unstructured data, mobile-first contacts, communication history, WhatsApp, and Voice.

Start here

Runnable Terminal examples

# Connected Push beginner examples
#
# Run one section at a time. Commands use curl and jq and call the same v1 API
# used by the Connected Push console. Sending a message or starting a call is a
# real, billable action. Use your own authorised test number.

## 1. Check access
# Confirm that the key and Business ID work.
# Required permissions: channels:read
# Result: Returns WhatsApp, Voice, and Instagram messaging as live channels. SMS remains reserved until its provider route is enabled.
# Run this in Terminal. Replace the API key and test mobile number.
command -v jq >/dev/null || { echo "Install jq first: https://jqlang.org/download/"; exit 1; }
export CP_BASE_URL="https://app.connectedpush.com"
read -rsp "Paste your Connected Push API key: " CP_API_KEY; echo
export CP_API_KEY
export CP_BUSINESS_ID="paste_business_id_here"
export CP_TEST_MOBILE="+919999999999"

curl --fail-with-body --silent --show-error \
  "$CP_BASE_URL/api/v1/channels?businessId=$CP_BUSINESS_ID" \
  -H "Authorization: Bearer $CP_API_KEY" | jq

## 2. Create a contact
# Save a mobile-first customer in the native Contacts data source.
# Required permissions: contacts:write
# Result: Prints the new contact ID. Re-running the same commands is safe.
# Run this in Terminal. Replace the API key and test mobile number.
command -v jq >/dev/null || { echo "Install jq first: https://jqlang.org/download/"; exit 1; }
export CP_BASE_URL="https://app.connectedpush.com"
read -rsp "Paste your Connected Push API key: " CP_API_KEY; echo
export CP_API_KEY
export CP_BUSINESS_ID="paste_business_id_here"
export CP_TEST_MOBILE="+919999999999"

# Contacts always belong to a category. This creates or reuses "API leads".
CATEGORY_ID=$(curl --fail-with-body --silent --show-error \
  "$CP_BASE_URL/api/v1/contacts/categories" -X POST \
  -H "Authorization: Bearer $CP_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: beginner-api-leads-category-v1" \
  -d "$(jq -n --arg businessId "$CP_BUSINESS_ID" \
    '{businessId: $businessId, name: "API leads"}')" | jq -er '.data.category.id')

CONTACT_ID=$(curl --fail-with-body --silent --show-error \
  "$CP_BASE_URL/api/v1/contacts" -X POST \
  -H "Authorization: Bearer $CP_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: beginner-contact-${CP_TEST_MOBILE//[^0-9]/}-v1" \
  -d "$(jq -n \
    --arg businessId "$CP_BUSINESS_ID" \
    --arg mobile "$CP_TEST_MOBILE" \
    --arg categoryId "$CATEGORY_ID" \
    '{businessId: $businessId, name: "API test contact", mobile: $mobile, categoryIds: [$categoryId]}')" \
  | jq -er '.data.contact.id')

echo "Contact created: $CONTACT_ID"

## 3. Send WhatsApp
# Find the connected number, send one message, and print its ID.
# Required permissions: channels:read, communications:write
# Result: Queues one real WhatsApp message. The same idempotency key never sends it twice.
# Run this in Terminal. Replace the API key and test mobile number.
command -v jq >/dev/null || { echo "Install jq first: https://jqlang.org/download/"; exit 1; }
export CP_BASE_URL="https://app.connectedpush.com"
read -rsp "Paste your Connected Push API key: " CP_API_KEY; echo
export CP_API_KEY
export CP_BUSINESS_ID="paste_business_id_here"
export CP_TEST_MOBILE="+919999999999"

# Connected Push discovers the Meta phone-number ID for this business.
PHONE_NUMBER_ID=$(curl --fail-with-body --silent --show-error \
  "$CP_BASE_URL/api/v1/channels/assignments?businessId=$CP_BUSINESS_ID&channel=whatsapp" \
  -H "Authorization: Bearer $CP_API_KEY" | jq -er '.data.phoneNumberId')

MESSAGE_ID=$(curl --fail-with-body --silent --show-error \
  "$CP_BASE_URL/api/v1/messages" -X POST \
  -H "Authorization: Bearer $CP_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: beginner-whatsapp-${CP_TEST_MOBILE//[^0-9]/}-v1" \
  -d "$(jq -n \
    --arg businessId "$CP_BUSINESS_ID" \
    --arg phoneNumberId "$PHONE_NUMBER_ID" \
    --arg to "$CP_TEST_MOBILE" \
    '{businessId: $businessId, phoneNumberId: $phoneNumberId, to: $to, type: "text", text: "Hello from Connected Push."}')" \
  | jq -er '.data.messageId')

echo "Message queued: $MESSAGE_ID"

## 4. Start a voice call
# Find a compatible Voice agent and call the test number.
# Required permissions: agents:read, voice:write
# Result: Starts one real call and prints its call ID. Calling requires an active Voice agent and approved number.
# Run this in Terminal. Replace the API key and test mobile number.
command -v jq >/dev/null || { echo "Install jq first: https://jqlang.org/download/"; exit 1; }
export CP_BASE_URL="https://app.connectedpush.com"
read -rsp "Paste your Connected Push API key: " CP_API_KEY; echo
export CP_API_KEY
export CP_BUSINESS_ID="paste_business_id_here"
export CP_TEST_MOBILE="+919999999999"

# Choose the newest active Voice agent that does not require contact variables.
AGENT_ID=$(curl --fail-with-body --silent --show-error \
  "$CP_BASE_URL/api/v1/agents?businessId=$CP_BUSINESS_ID" \
  -H "Authorization: Bearer $CP_API_KEY" \
  | jq -er '[.data.agents[] | select(.channel == "voice" and .status == "active" and .contactContextRequired == false)] | first | .id')

CALL_ID=$(curl --fail-with-body --silent --show-error \
  "$CP_BASE_URL/api/v1/voice/calls" -X POST \
  -H "Authorization: Bearer $CP_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: beginner-call-${CP_TEST_MOBILE//[^0-9]/}-v1" \
  -d "$(jq -n \
    --arg businessId "$CP_BUSINESS_ID" \
    --arg agentId "$AGENT_ID" \
    --arg toNumber "$CP_TEST_MOBILE" \
    '{businessId: $businessId, agentId: $agentId, toNumber: $toNumber}')" \
  | jq -er '.data.callId')

echo "Call started: $CALL_ID"

## 5. Read contact history
# Find a contact and read its WhatsApp and Voice timeline.
# Required permissions: contacts:read, communications:read
# Result: Returns the newest messages, transcripts, and call outcomes stored for that contact.
# Run this in Terminal. Replace the API key and test mobile number.
command -v jq >/dev/null || { echo "Install jq first: https://jqlang.org/download/"; exit 1; }
export CP_BASE_URL="https://app.connectedpush.com"
read -rsp "Paste your Connected Push API key: " CP_API_KEY; echo
export CP_API_KEY
export CP_BUSINESS_ID="paste_business_id_here"
export CP_TEST_MOBILE="+919999999999"

CONTACT_ID=$(curl --fail-with-body --silent --show-error \
  "$CP_BASE_URL/api/v1/contacts?businessId=$CP_BUSINESS_ID&search=${CP_TEST_MOBILE//+/%2B}" \
  -H "Authorization: Bearer $CP_API_KEY" \
  | jq -er '.data.contacts | first | .id')

curl --fail-with-body --silent --show-error \
  "$CP_BASE_URL/api/v1/contacts/$CONTACT_ID/timeline?businessId=$CP_BUSINESS_ID" \
  -H "Authorization: Bearer $CP_API_KEY" | jq
Advanced

All endpoints

54 operations
GET/api/v1/contracts/whatsapp-automation

Return the public WhatsApp automation contract version and emitted event types.

GET/api/v1/webhook-subscriptions

List tenant-scoped WhatsApp and Instagram webhook subscriptions without exposing signing secrets.

POST/api/v1/webhook-subscriptions

Subscribe an external automation backend to signed WhatsApp or Instagram messaging events.

PATCH/api/v1/webhook-subscriptions/{subscriptionId}

Update callback URL, subscribed events, or active/paused state for a tenant-owned subscription.

DELETE/api/v1/webhook-subscriptions/{subscriptionId}

Permanently revoke a tenant-owned webhook subscription.

POST/api/v1/webhook-subscriptions/{subscriptionId}/rotate-secret

Replace the signing secret immediately and return the new secret once.

POST/api/v1/media

Upload canonical base64 image bytes to Meta WhatsApp Media API and cache the provider media id.

POST/api/v1/messages

Queue a WhatsApp or Instagram message through Connected Push.

GET/api/v1/messages/{messageId}

Read authoritative message delivery state and provider timestamps.

GET/api/v1/channels

List channel keys, labels, live readiness, and assignment mode. WhatsApp and outbound Voice are live.

GET/api/v1/channels/instagram

Read tenant-scoped Instagram professional account connection metadata without exposing its token.

DELETE/api/v1/channels/instagram

Revoke Connected Push use of the tenant Instagram connection and clear provider account assets.

GET/api/v1/agents

List business agents, stable reference names, and channel mapping.

POST/api/v1/agents

Create an agent for WhatsApp, SMS, Voice, or Other. Attach Data Sources, contact categories, declared variables, and provider-neutral voice settings. WhatsApp can be assigned during creation.

PATCH/api/v1/agents

Update a tenant-owned agent using the same channel, prompt, Data Source, and voice-settings contract as creation.

DELETE/api/v1/agents

Archive a tenant-owned agent so it can no longer be selected for new conversations.

GET/api/v1/data-sources

List the business's structured and unstructured Data Sources, including fields explicitly available for contact variables.

POST/api/v1/data-sources

Create a tenant structured table/JSON source or unstructured text Data Source.

PATCH/api/v1/data-sources

Update Data Source metadata, status, or unstructured content.

DELETE/api/v1/data-sources

Archive a tenant Data Source.

POST/api/v1/data-sources/upload

Upload a CSV, TSV, JSON, XLSX, or XLSM asset for lossless asynchronous ingestion into an immutable version.

GET/api/v1/data-sources/ingestions

Inspect ingestion stages, immutable version status, validation issues, and columns requiring review.

PATCH/api/v1/data-sources/ingestions

Submit reviewed column interpretations and atomically activate the validated version.

GET/api/v1/contacts

List mobile-first tenant contacts with categories and communication rollups.

POST/api/v1/contacts

Create one mobile-first contact in a tenant-owned category.

DELETE/api/v1/contacts

Delete selected tenant contacts or every contact in a tenant category.

POST/api/v1/contacts/imports

Import structured CSV contact data into one or more tenant categories.

GET/api/v1/contacts/categories

List tenant contact categories with cursor pagination and contact counts.

POST/api/v1/contacts/categories

Create a tenant contact category.

DELETE/api/v1/contacts/categories

Delete a tenant category after explicit name confirmation.

GET/api/v1/contacts/{contactId}

Read one contact with categories and per-channel activity rollups. When campaignId is supplied, include that campaign's shared contact summary.

PATCH/api/v1/contacts/{contactId}

Update one contact, category membership, and communication-blocked state.

GET/api/v1/contacts/{contactId}/timeline

Read a bounded cross-channel timeline of messages, transcripts, and call outcomes, optionally limited to one campaign. Recording content requires voice:read through the call API.

POST/api/v1/channel-participants/{participantId}/link-contact

Resolve a mobile-first contact and link the participant's prior channel history without OTP verification.

GET/api/v1/channels/assignments

Read WhatsApp phone-number assignment state and assignable agents.

PATCH/api/v1/channels/assignments

Assign a WhatsApp agent to the connected Meta phone number.

GET/api/v1/voice/calls

Cursor-paginated outbound calls with immutable call IDs, status, duration, charge, transcript and recording availability, plus canonical end attribution.

POST/api/v1/voice/calls

Start one outbound call with an active Voice Call agent. Choose exactly one target: a scoped contact or a direct E.164 number.

POST/api/v1/voice/calls/batch

Start calls for 1-20 scoped contacts through the same canonical call service. Each contact resolves its own declared variables and receives an independent billing reservation.

GET/api/v1/voice/calls/resolve

Resolve the selected agent's allowlisted contact variables and destination before placement. This endpoint exposes contact data and therefore requires both voice and contact read scopes.

GET/api/v1/voice/calls/{callId}

Return one canonical call report with who ended the call, timestamp-ordered transcript, and a short-lived recording URL when the recording is ready.

GET/api/v1/voice/calls/{callId}/transcript

Download the canonical timestamped call transcript as UTF-8 plain text with an attachment filename.

DELETE/api/v1/voice/calls/{callId}

Durably request cancellation of a queued, ringing, or answered call. Carrier-backed calls remain cancelling until the carrier confirms a terminal result.

GET/api/v1/campaigns

List channel-neutral campaigns and their latest Voice, WhatsApp, or SMS iteration.

POST/api/v1/campaigns

Create one campaign objective with an initial channel-specific iteration and immutable audience membership.

GET/api/v1/campaigns/{campaignId}

Read one tenant-owned campaign and its current iteration.

PATCH/api/v1/campaigns/{campaignId}

Start, pause, or cancel the current campaign iteration.

GET/api/v1/campaigns/{campaignId}/iterations

List ordered channel-specific runs under a stable campaign ID.

POST/api/v1/campaigns/{campaignId}/iterations

Select contacts from prior outcomes and create a Voice or WhatsApp iteration without creating another campaign.

GET/api/v1/campaigns/{campaignId}/memberships

List immutable per-contact iteration membership and outcome history.

GET/api/v1/campaigns/{campaignId}/activities

List attributed calls and messages newest first with contact, iteration, status, call duration, and activity time. Filter by contact, iteration, channel, or status.

GET/api/v1/campaigns/{campaignId}/summary-runs

List append-only AI summary runs and their assessment progress for a campaign.

POST/api/v1/campaigns/{campaignId}/summary-runs

Calculate a maximum AI assessment charge or confirm that exact estimate before processing.

GET/api/v1/campaigns/{campaignId}/exports

Stream one campaign conclusion per unique contact with the columns Contact, AI Summary, and Next Action.

Advanced

LLM integration context

Open

Use the generated Markdown brief when an AI coding tool needs the complete API contract and safety rules.

Download