Build an Integration End-to-End
This guide walks through everything you need to run Your AI Connector from your own code, without ever opening the dashboard. By the end you will have built a minimal integration that:
- Authenticates with an API key
- Creates an AI Agent and configures its assistant behaviour
- Connects a messaging channel (we use WhatsApp Web as the worked example) and points it at the Agent
- Imports contacts
- Sends and reads messages
- Reads analytics
- Subscribes to webhooks for real-time events
Every step links to the full resource guide so you can dig into the details when you need them. This page is the map; the resource guides are the territory.
Before you start. API access is a paid feature. If your plan does not include it, every request returns
403. See API Access to confirm it is enabled, and Authentication for all the ways to pass your key.
All paths below are relative to the base URL:
https://api.youraiconnector.com/v1
Step 1 — Get an API key and make your first request
Your API key lives in the app under Settings → Integrations → API Key — its own section under Integrations, separate from Webhooks, which only appears once API access is on the plan. Generate one, copy it, and store it somewhere safe (a server-side secret store or environment variable — never in browser code). Full instructions are in API Access.
Once you have a key, confirm it works by calling the health endpoint. There are several ways to send the key; the simplest is the ?apiKey= query parameter, but for real code prefer the X-API-Key header so the key never ends up in server logs or browser history.
cURL
curl "https://api.youraiconnector.com/v1/health?apiKey=YOUR_API_KEY"
JavaScript
const BASE = "https://api.youraiconnector.com/v1";
const headers = { "X-API-Key": "YOUR_API_KEY", "Content-Type": "application/json" };
const res = await fetch(`${BASE}/health`, { headers });
const data = await res.json();
console.log(data); // { "success": true, ... }
Python
import requests
BASE = "https://api.youraiconnector.com/v1"
HEADERS = {"X-API-Key": "YOUR_API_KEY", "Content-Type": "application/json"}
res = requests.get(f"{BASE}/health", headers=HEADERS)
print(res.json()) # { "success": true, ... }
Every successful response is wrapped in the same envelope — a success: true field plus the result data. Errors return success: false with an error message and an error_code. See Errors & Pagination for the full list and for how list endpoints page with ?limit and ?cursor.
Rate limit. Authenticated requests are capped at 300 per minute (with a wider 1,200/minute ceiling per account). Going over returns
429; back off and retry.
Step 2 — Create an AI Agent
An AI Agent is the unit that holds your assistant’s behaviour: its instructions, its goal, its active hours, and how it talks to contacts. It is what answers a conversation, so this is the natural first thing to create.
Create one with POST /agents. name is the only field worth sending up front; everything else can be set with the bot-config call below.
cURL
curl -X POST "https://api.youraiconnector.com/v1/agents" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Inbound WhatsApp Leads",
"language": "en"
}'
JavaScript
const res = await fetch(`${BASE}/agents`, {
method: "POST",
headers,
body: JSON.stringify({
name: "Inbound WhatsApp Leads",
language: "en",
}),
});
const { agent_id } = await res.json();
Python
res = requests.post(
f"{BASE}/agents",
headers=HEADERS,
json={"name": "Inbound WhatsApp Leads", "language": "en"},
)
agent_id = res.json()["agent_id"]
A successful create returns 201 with the new ID:
{
"success": true,
"agent_id": "abc123agent"
}
Save the agent_id — you will reference it when routing channels.
Configure the assistant
PUT /agents/{agentId}/bot-config sets the assistant’s behaviour. It merges the fields you send into the existing configuration, so anything you leave out is preserved:
curl -X PUT "https://api.youraiconnector.com/v1/agents/abc123agent/bot-config" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"instructions": "Greet warmly, answer questions about our services, and offer to book a call.",
"goal": "Book a discovery call.",
"ai_speed": "balanced"
}'
Set active hours with PUT /agents/{agentId}/active-hours so the assistant only replies during business hours; outside those windows it does not reply automatically.
Knowledge base. To have the assistant answer from your own content, attach FAQs. See the FAQs guide.
Legacy: classic campaigns. Accounts that still have a Campaigns page create the same assistant behaviour on a campaign instead (
POST /campaignswith atypeand abotobject, thenPUT /campaigns/{campaignId}/bot-config). The full campaign field list and lifecycle controls are in the Campaigns guide. If you are building something new, create an Agent.
Step 3 — Connect a channel
An Agent needs a way to send and receive messages. Seven connect flows can be driven from the API: WhatsApp Business, WhatsApp Web, Instagram and Messenger together (one shared Meta flow), Instagram personal accounts, Telegram, LINE, and Viber. The remaining channels — SMS, email, the chat widget and custom channels among them — are set up in the dashboard rather than over REST, and once they are connected the messaging, contact and routing endpoints work on them exactly the same way. GET /channels is the live source of truth for what a given account actually has connected:
curl "https://api.youraiconnector.com/v1/channels?apiKey=YOUR_API_KEY"
The full set of connect/disconnect flows for each channel is documented in the Channels guide. Below we walk through WhatsApp Web end to end, because it shows the most interesting pattern: a QR-code pairing flow that your wrapper has to render and poll.
Worked example: pair WhatsApp Web by QR code
WhatsApp Web pairing is a three-call dance — start, fetch the QR, poll until connected.
1. Start the pairing session. Pass the number you want to connect in E.164 format.
curl -X POST "https://api.youraiconnector.com/v1/channels/whatsapp-web/connections" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "phone_number": "+15551230000" }'
await fetch(`${BASE}/channels/whatsapp-web/connections`, {
method: "POST",
headers,
body: JSON.stringify({ phone_number: "+15551230000" }),
});
requests.post(
f"{BASE}/channels/whatsapp-web/connections",
headers=HEADERS,
json={"phone_number": "+15551230000"},
)
2. Fetch the QR code and show it to the user. Poll this every 10–15 seconds. The response includes the raw qr_code payload (render it as a QR image yourself) and a ready-to-display qr_data_url.
curl "https://api.youraiconnector.com/v1/channels/whatsapp-web/connections/+15551230000/qr?apiKey=YOUR_API_KEY"
{
"success": true,
"phone_number": "+15551230000",
"status": "qr_pending",
"qr_code": "2@abc...",
"qr_data_url": "data:image/png;base64,iVBORw0KGgo..."
}
In your wrapper’s UI, drop qr_data_url straight into an <img src="..."> and ask the user to scan it from WhatsApp → Linked Devices on their phone. If the QR expires (a 410 response), restart from step 1 to get a fresh one.
3. Poll the status until it connects. After the user scans, keep polling the status endpoint until it reports connected (the service may also report open). Treat disconnected and not_initialized as terminal failures.
import time
PHONE = "+15551230000"
while True:
res = requests.get(
f"{BASE}/channels/whatsapp-web/connections/{PHONE}/status",
headers=HEADERS,
)
status = res.json()["status"]
if status in ("connected", "open"):
print("Connected!")
break
if status in ("disconnected", "not_initialized"):
raise RuntimeError(f"Pairing failed: {status}")
time.sleep(5)
async function waitForConnection(phone) {
while (true) {
const res = await fetch(
`${BASE}/channels/whatsapp-web/connections/${encodeURIComponent(phone)}/status`,
{ headers }
);
const { status } = await res.json();
if (status === "connected" || status === "open") return;
if (status === "disconnected" || status === "not_initialized") {
throw new Error(`Pairing failed: ${status}`);
}
await new Promise((r) => setTimeout(r, 5000));
}
}
Heads up. Each connected WhatsApp Web number carries a recurring monthly maintenance charge until you disconnect it (
DELETE /channels/whatsapp-web/connections/{phoneNumber}).
Route the channel to your Agent
Connecting a channel makes it work; routing it tells the platform which AI Agent should answer brand-new inbound conversations on it. Set the channel-default Entry Point for the channel, naming the Agent you created in Step 2:
curl -X PUT "https://api.youraiconnector.com/v1/entry-points/channel-defaults" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "channel": "whatsapp_web", "agent_id": "abc123agent" }'
Repeat the call once per channel — one channel default per channel. To leave a channel with no Agent answering it, call DELETE /entry-points/channel-defaults?channel=whatsapp_web; to check whether the Entry Points ladder is live for the account, call GET /entry-points/routing-status. The older POST /channels/campaign map is retained for rollback only and is no longer consulted for inbound routing. See the Channels guide for the other channel types and for the WhatsApp Business OAuth flow.
Step 4 — Import your contacts
With a channel live, load the people you want to reach. The import endpoint takes up to 500 records per call. Each record needs a phone_number in international format; everything else is optional. Records with bad numbers, unsupported channels, or numbers that already exist are skipped — and each skip is reported with its index and reason, so you can retry just the failures.
cURL
curl -X POST "https://api.youraiconnector.com/v1/contacts/import" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"contacts": [
{ "phone_number": "+12025551234", "first_name": "Ann", "last_name": "Lee" },
{ "phone_number": "+12025551235", "first_name": "Bob" }
],
"defaultChannel": "whatsapp_web"
}'
JavaScript
const res = await fetch(`${BASE}/contacts/import`, {
method: "POST",
headers,
body: JSON.stringify({
contacts: [
{ phone_number: "+12025551234", first_name: "Ann", last_name: "Lee" },
{ phone_number: "+12025551235", first_name: "Bob" },
],
defaultChannel: "whatsapp_web",
}),
});
const result = await res.json();
console.log(`${result.imported} imported, ${result.skipped.length} skipped`);
Python
res = requests.post(
f"{BASE}/contacts/import",
headers=HEADERS,
json={
"contacts": [
{"phone_number": "+12025551234", "first_name": "Ann", "last_name": "Lee"},
{"phone_number": "+12025551235", "first_name": "Bob"},
],
"defaultChannel": "whatsapp_web",
},
)
result = res.json()
print(f"{result['imported']} imported, {len(result['skipped'])} skipped")
The response tells you exactly what happened:
{
"success": true,
"imported": 2,
"contact_ids": ["contactId1", "contactId2"],
"skipped": []
}
For one-at-a-time creation, list/lookup, lists, tags, and custom fields, see the Contacts guide.
Step 5 — Send and read messages
Send a message
The simplest send is channel-agnostic: give the contact’s identity and the message body, and the platform delivers it on whatever channel the contact is on. You can target by contact_id, or by channel plus the matching identity field (phone_number for WhatsApp/WhatsApp Web/SMS, instagram_id for Instagram, and so on).
cURL
curl -X POST "https://api.youraiconnector.com/v1/contacts/send" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"channel": "whatsapp_web",
"phone_number": "+12025551234",
"body": "Hi Ann! Thanks for reaching out."
}'
JavaScript
const res = await fetch(`${BASE}/contacts/send`, {
method: "POST",
headers,
body: JSON.stringify({
channel: "whatsapp_web",
phone_number: "+12025551234",
body: "Hi Ann! Thanks for reaching out.",
}),
});
const { message_id } = await res.json();
Python
res = requests.post(
f"{BASE}/contacts/send",
headers=HEADERS,
json={
"channel": "whatsapp_web",
"phone_number": "+12025551234",
"body": "Hi Ann! Thanks for reaching out.",
},
)
message_id = res.json()["message_id"]
Delivery is asynchronous — a 201 means the message was accepted and queued, not yet delivered. (Contacts with do-not-disturb or private mode on are rejected with a 422.)
{
"success": true,
"message_id": "aB3dE5fG7hI9jK1lM2nO",
"contact_id": "contact123",
"channel": "whatsapp_web"
}
Read a conversation
To read messages back, list them by contact, newest first, with cursor pagination. Pass the next_cursor from one response as the cursor of the next to walk back through the history.
curl "https://api.youraiconnector.com/v1/contacts/contact123/messages?limit=50&apiKey=YOUR_API_KEY"
res = requests.get(
f"{BASE}/contacts/contact123/messages",
headers=HEADERS,
params={"limit": 50},
)
page = res.json()
for msg in page["messages"]:
print(msg)
next_cursor = page["next_cursor"] # pass back as ?cursor= for the next page
You can also filter by content type (?filter=text|media|tool_use) or direction (?direction=inbound|outbound). The Messages guide covers media attachments, marking messages read, and the per-session message views.
Don’t poll for replies. Listing messages on a timer works, but it wastes requests and adds lag. For incoming messages, use webhooks instead — that’s Step 7.
Step 6 — Read analytics
Once messages are flowing, the analytics summary gives you aggregated counts over a date range: sent, delivered, read, replied, booked, contacts created, and credits spent/recharged. You get both range totals and a zero-filled per-day series — perfect for a dashboard chart. Optionally scope it to a single campaign with campaign_id (the examples below use a placeholder campaign ID, abc123campaign); leave the parameter off for account-wide totals.
curl "https://api.youraiconnector.com/v1/analytics/summary?from=2026-05-01&to=2026-05-31&campaign_id=abc123campaign&apiKey=YOUR_API_KEY"
const params = new URLSearchParams({
from: "2026-05-01",
to: "2026-05-31",
campaign_id: "abc123campaign",
});
const res = await fetch(`${BASE}/analytics/summary?${params}`, { headers });
const { totals, by_date } = await res.json();
res = requests.get(
f"{BASE}/analytics/summary",
headers=HEADERS,
params={"from": "2026-05-01", "to": "2026-05-31", "campaign_id": "abc123campaign"},
)
data = res.json()
totals = data["totals"]
by_date = data["by_date"]
The range defaults to the last 30 days and is capped at 366. For credit-by-credit usage records and AI cost breakdowns, see the Analytics guide.
Step 7 — Subscribe to webhooks for real-time events
Polling is fine for a quick script, but a real integration should be push-based. Webhooks let the platform call your server the moment something happens — a new contact, a reply, a booked appointment, a chat concluded.
First, discover the exact event names you can subscribe to:
curl "https://api.youraiconnector.com/v1/webhooks/events?apiKey=YOUR_API_KEY"
{
"success": true,
"events": [
"Contact Created",
"Human Alerted",
"Appointment Booked",
"Replies",
"New Message",
"Chat Concluded",
"Task Created",
"Daily Summary Created"
]
}
Then create a subscription pointing at an HTTPS URL on your server. Use the exact event strings from the call above.
cURL
curl -X POST "https://api.youraiconnector.com/v1/webhooks" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://hooks.example.com/incoming",
"subscribed_to": ["Contact Created", "Replies"],
"name": "Lead updates hook"
}'
JavaScript
const res = await fetch(`${BASE}/webhooks`, {
method: "POST",
headers,
body: JSON.stringify({
url: "https://hooks.example.com/incoming",
subscribed_to: ["Contact Created", "Replies"],
name: "Lead updates hook",
}),
});
const { webhook_id } = await res.json();
Python
res = requests.post(
f"{BASE}/webhooks",
headers=HEADERS,
json={
"url": "https://hooks.example.com/incoming",
"subscribed_to": ["Contact Created", "Replies"],
"name": "Lead updates hook",
},
)
webhook_id = res.json()["webhook_id"]
{
"success": true,
"webhook_id": "1",
"webhook": {
"id": "1",
"name": "Lead updates hook",
"url": "https://hooks.example.com/incoming",
"subscribed_to": ["Contact Created", "Replies"],
"subscribed_to_tags": [],
"created_at": "2026-06-09T12:00:00.000Z"
}
}
The URL must use HTTPS and be publicly reachable. From here on, your server receives a POST for each subscribed event. You can send a test delivery, check a subscription’s health, and re-enable a subscription that was auto-disabled after repeated failures — see the Webhooks guide and the integrations-level Webhooks page for payload shapes and verification.
Putting it all together
Here is the whole flow at a glance:
| Step | Goal | Key call |
|---|---|---|
| 1 | Authenticate | GET /health |
| 2 | Create + tune the assistant | POST /agents, PUT /agents/{id}/bot-config, PUT /agents/{id}/active-hours |
| 3 | Connect a channel and route it | POST /channels/whatsapp-web/connections → poll QR + status → PUT /entry-points/channel-defaults |
| 4 | Load contacts | POST /contacts/import |
| 5 | Send & read | POST /contacts/send, GET /contacts/{id}/messages |
| 6 | Measure | GET /analytics/summary |
| 7 | React in real time | POST /webhooks |
A minimal wrapper is just these seven calls wired into your own UI. From there, layer in the per-resource guides as you need more:
- Campaigns · Contacts · FAQs · Messages · Appointments
- Channels · Templates · Analytics · Webhooks · API Keys
- New here? Getting Started · Authentication · Errors & Pagination
Stuck on something this guide does not cover? Email hi@youraiconnector.com.