Channels
The Channel object
Every connect, status, and refresh endpoint returns a channel object:
{
"id": 5,
"type": "whatsapp",
"username": "+966501234567",
"is_connected": true,
"sync_status": "OK",
"last_synced_at": "2026-03-11T10:00:00+03:00"
}
| Field | Type | Description |
|---|---|---|
id | integer | Channel setting ID |
type | string | whatsapp, telegram, or instagram |
username | string|null | Phone number or Instagram username |
is_connected | boolean | Whether the channel is currently active |
sync_status | string | Live status from Unipile — see table below |
last_synced_at | string|null | ISO 8601 timestamp of last sync |
sync_status values
| Value | Meaning |
|---|---|
OK | Connected and healthy |
CONNECTING | Account is initializing |
SYNC_SUCCESS | Sync completed successfully |
CREDENTIALS | Password changed — re-connect required |
ERROR | Generic error — try refresh or re-connect |
STOPPED | Account paused |
CREATION_FAIL | QR connection attempt failed |
WhatsApp uses a QR code flow. Your app generates a QR code and the end user scans it with their WhatsApp mobile app.
Connect WhatsApp
POST /api/v1/channels/whatsapp/connect
Generates a QR code for WhatsApp login. Returns the raw QR string and an account_id to poll with. Returns 409 if WhatsApp is already connected — disconnect first.
curl -X POST https://dashboard.skylightchat.com/api/v1/channels/whatsapp/connect \
-H "X-Api-Key: YOUR_API_KEY"
Response
{
"success": true,
"data": {
"account_id": "wa_abc123",
"qr_code": "2@AbCdEfGh...,1234..."
},
"message": "QR code generated. Scan with WhatsApp on your phone..."
}
Rendering the QR code: Pass the
qr_codestring to any standard QR library (e.g.qrcode.js,python-qrcode). The string is in WhatsApp's multi-device format — do not treat it as a URL.
Get WhatsApp status
GET /api/v1/channels/whatsapp/status
Poll this endpoint after the user scans the QR code. Pass the account_id returned by the connect call.
Query parameters
| Parameter | Type | Description |
|---|---|---|
account_id | string | Optional. Returned by /connect. Omit to get the current connected account. |
curl "https://dashboard.skylightchat.com/api/v1/channels/whatsapp/status?account_id=wa_abc123" \
-H "X-Api-Key: YOUR_API_KEY"
Response
{
"success": true,
"data": {
"id": 5,
"type": "whatsapp",
"username": "+966501234567",
"is_connected": true,
"sync_status": "OK",
"last_synced_at": "2026-03-11T10:00:00+03:00",
"completed": true,
"in_progress": false
}
}
completed | in_progress | Meaning |
|---|---|---|
false | true | Waiting for QR scan — keep polling every 2–3 seconds |
true | false | Connected successfully |
Refresh WhatsApp status
POST /api/v1/channels/whatsapp/refresh
Pulls the latest account status from Unipile and updates local records. Useful after a disruption or to verify the account is healthy.
curl -X POST https://dashboard.skylightchat.com/api/v1/channels/whatsapp/refresh \
-H "X-Api-Key: YOUR_API_KEY"
Returns the updated channel object.
Disconnect WhatsApp
POST /api/v1/channels/whatsapp/disconnect
Permanently removes the WhatsApp account from Unipile and deletes local settings. Returns 204 No Content on success.
Returns 422 if an outreach campaign is currently running or paused on this channel — cancel it first.
curl -X POST https://dashboard.skylightchat.com/api/v1/channels/whatsapp/disconnect \
-H "X-Api-Key: YOUR_API_KEY"
Telegram
Telegram also uses a QR code flow. The user scans via Telegram app → Settings → Devices → Link Desktop Device.
completed: true — this usually takes 5–15 seconds after the QR is scanned.Connect Telegram
POST /api/v1/channels/telegram/connect
curl -X POST https://dashboard.skylightchat.com/api/v1/channels/telegram/connect \
-H "X-Api-Key: YOUR_API_KEY"
Response
{
"success": true,
"data": {
"account_id": "tg_xyz789",
"qr_code": "tg://login?token=ABCDEFGHIJ..."
},
"message": "QR code generated. Open Telegram → Settings → Devices → Link Desktop Device, then scan."
}
Get Telegram status
GET /api/v1/channels/telegram/status
Same polling interface as WhatsApp. Pass ?account_id=<id> from the connect response.
curl "https://dashboard.skylightchat.com/api/v1/channels/telegram/status?account_id=tg_xyz789" \
-H "X-Api-Key: YOUR_API_KEY"
completed | in_progress | Meaning |
|---|---|---|
false | true | Waiting — keep polling |
true | false | Connected |
false | false | Failed — generate a new QR code |
Refresh Telegram status
POST /api/v1/channels/telegram/refresh
Returns the updated channel object.
Disconnect Telegram
POST /api/v1/channels/telegram/disconnect
Returns 204 No Content on success.
Instagram uses credential-based authentication — no QR code. You pass the username and password directly to the API, and we authenticate through Unipile's native auth. Instagram 2FA is handled inline.
Connect Instagram
POST /api/v1/channels/instagram/connect
Request body
{
"username": "my_brand_account",
"password": "secretpassword",
"country": "SA"
}
| Field | Type | Required | Description |
|---|---|---|---|
username | string | ✓ | Instagram username or email |
password | string | ✓ | Instagram password |
country | string | No | ISO 3166-1 alpha-2 country code. Default: SA. Used to route the connection geographically. |
curl -X POST https://dashboard.skylightchat.com/api/v1/channels/instagram/connect \
-H "X-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"username": "my_brand", "password": "secret", "country": "SA"}'
Response — connected immediately
{
"success": true,
"data": {
"id": 7,
"type": "instagram",
"username": "my_brand",
"is_connected": true,
"sync_status": "OK",
"last_synced_at": "2026-03-11T10:00:00+03:00"
}
}
Response — 2FA required
{
"success": true,
"data": {
"requires_2fa": true,
"account_id": "ig_abc123",
"checkpoint_type": "OTP"
},
"message": "A verification code has been sent. Submit it to POST /channels/instagram/2fa."
}
When requires_2fa: true is returned, prompt your user for the verification code Instagram sent to their phone or email, then call the 2FA endpoint below.
Solve Instagram 2FA
POST /api/v1/channels/instagram/2fa
Submit the verification code during the Instagram connect flow.
Request body
{
"account_id": "ig_abc123",
"code": "123456"
}
| Field | Type | Required | Description |
|---|---|---|---|
account_id | string | ✓ | From the connect response |
code | string | ✓ | The verification code the user received |
Response — connected
{
"success": true,
"data": {
"id": 7,
"type": "instagram",
"username": "my_brand",
"is_connected": true,
"sync_status": "CONNECTING"
},
"message": "Instagram connected successfully. Account is syncing."
}
Response — another verification round
{
"success": true,
"data": {
"requires_2fa": true,
"account_id": "ig_abc123",
"checkpoint_type": "OTP"
},
"message": "Additional verification required. Submit your code again."
}
Resend Instagram 2FA code
POST /api/v1/channels/instagram/2fa/resend
Resends the verification code to the user's Instagram-registered phone or email.
Request body
{ "account_id": "ig_abc123" }
Response
{ "success": true, "message": "Verification code resent successfully." }
Get Instagram status
GET /api/v1/channels/instagram/status
Returns the current Instagram connection status from local records. Use /refresh to pull the latest status from Unipile.
curl https://dashboard.skylightchat.com/api/v1/channels/instagram/status \
-H "X-Api-Key: YOUR_API_KEY"
Returns the channel object.
Refresh Instagram status
POST /api/v1/channels/instagram/refresh
Syncs the account status from Unipile. Useful after a CREDENTIALS or ERROR state to see if the issue has been resolved.
Returns the updated channel object.
Disconnect Instagram
POST /api/v1/channels/instagram/disconnect
Removes the Instagram account from Unipile and deletes local settings. Returns 204 No Content on success.
Connect flow summary
WhatsApp & Telegram (QR code)
────────────────────────────────────────────────────
1. POST /channels/{channel}/connect
→ { account_id, qr_code }
2. Render qr_code as a QR image for the user to scan
3. GET /channels/{channel}/status?account_id={id}
Poll every 2–3 seconds until:
→ { completed: true } ✓ Done
Instagram (credentials)
────────────────────────────────────────────────────
1. POST /channels/instagram/connect { username, password }
→ Connected: { is_connected: true } ✓ Done
→ 2FA required: { requires_2fa: true, account_id, checkpoint_type }
2. (If 2FA) POST /channels/instagram/2fa { account_id, code }
→ Connected: { is_connected: true } ✓ Done
→ Another round: { requires_2fa: true } → repeat step 2
