SkyLight Chat
API Reference

Channels

Connect, monitor, refresh, and disconnect WhatsApp, Telegram, and Instagram channels via the API.

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"
}
FieldTypeDescription
idintegerChannel setting ID
typestringwhatsapp, telegram, or instagram
usernamestring|nullPhone number or Instagram username
is_connectedbooleanWhether the channel is currently active
sync_statusstringLive status from Unipile — see table below
last_synced_atstring|nullISO 8601 timestamp of last sync

sync_status values

ValueMeaning
OKConnected and healthy
CONNECTINGAccount is initializing
SYNC_SUCCESSSync completed successfully
CREDENTIALSPassword changed — re-connect required
ERRORGeneric error — try refresh or re-connect
STOPPEDAccount paused
CREATION_FAILQR connection attempt failed

WhatsApp

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_code string 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

ParameterTypeDescription
account_idstringOptional. 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
  }
}
completedin_progressMeaning
falsetrueWaiting for QR scan — keep polling every 2–3 seconds
truefalseConnected 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.

Telegram connection is confirmed asynchronously via Unipile webhook. Keep polling the status endpoint until 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"
completedin_progressMeaning
falsetrueWaiting — keep polling
truefalseConnected
falsefalseFailed — 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

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"
}
FieldTypeRequiredDescription
usernamestringInstagram username or email
passwordstringInstagram password
countrystringNoISO 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"
}
FieldTypeRequiredDescription
account_idstringFrom the connect response
codestringThe 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