Developers
Build on AI Desk.
Three ways in: drop-in widget, dashboard, and API v1. Base URL https://aidesk.sg.
Widget embed
Paste your bot snippet before </body> (find it in your dashboard when you build a bot):
<script src="https://aidesk.sg/api/e?uid=YOUR_BOT_UID" async></script>API v1 (key-authed)
Mint a key in your dashboard (API keys section: the secret shows once). Send it as a bearer token:
curl https://aidesk.sg/api/v1/bots \
-H "Authorization: Bearer adsk_YOUR_KEY"List bots
GET /api/v1/bots
→ { ok, bots: [{ uid, name, domain, status, snippet }] }Conversations
GET /api/v1/conversations?botUid=UID
→ { ok, conversations: [{ id, name, email,
created_at, last_message_at, messages }] }Analytics
GET /api/v1/analytics?botUid=UID
→ { ok, analytics: { sessions, sessions_7d,
sessions_30d, sessions_month, questions,
questions_7d, questions_month, leads } }Errors: 401 invalid/revoked key, 404 bot not yours, 400 missing botUid. Keys only ever see bots owned by the key owner.
Lead webhook (outbound)
Every captured lead also POSTs as JSON to the URL you save on the bot's Conversations page. Point it at a Zapier catch hook, a Slack incoming webhook, or your own endpoint:
POST YOUR_URL (Content-Type: application/json)
{ "event": "lead.created",
"bot_uid": "UID", "bot_name": "My bot",
"session_id": "…", "name": "Jane",
"email": "jane@co.com", "message": "…",
"inbox_url": "https://aidesk.sg/dashboard/bots/UID/conversations" }One URL per bot, https only. A dead hook never breaks the chat that posted it. The lead still lands in your inbox and Conversations page.
MCP server
Point Claude, ChatGPT, or any MCP client at https://aidesk.sg/api/mcp with your API key as the Bearer [REDACTED] Streamable HTTP, JSON-RPC 2.0. Four tools: list_bots, ask_bot, get_conversations, get_analytics.
POST /api/mcp (Authorization: Bearer [REDACTED])
{ "jsonrpc": "2.0", "id": 1,
"method": "tools/call",
"params": { "name": "ask_bot",
"arguments": { "botUid": "UID",
"question": "What do you charge?" } } }MCP answers come from the live bot: instructions, training, and free-tier limits all apply. API asks land in one thread per key so your inbox stays honest about usage.
Chat protocol (widget wire format)
The widget talks to POST /api/chat/[uid] with server-sent events back. Same endpoint powers the dashboard playground:
POST /api/chat/YOUR_BOT_UID
Content-Type: application/json
{ "messages": [
{ "role": "user",
"parts": [{ "type": "text", "text": "What do you charge?" }] }
]}
← text/event-stream, JSON frames;
concatenate type "text-delta" deltas for the reply.Keep the uid server-side when you call this directly. Anyone with the uid can chat, by design (it is printed in your public embed snippet).