Channels & Embeds
Embedded web chat
Add a text chat with your OnCore assistant to any website.
Embedded web chat lets visitors text with a OnCore assistant from your website. Your backend mints a short-lived session token; the browser then talks to OnCore directly with that token — your API key never leaves your server.
Keep the API key server-side
The tenant API key is a server-side secret. Call /web-chat/session from your backend, never from browser JavaScript. The browser only ever holds the short-lived session token.
Integration flow#
Mint a session token (backend)#
Call POST /web-chat/session with your API key. phoneNumber must be E.164 and assigned to one of your tenant's assistants — it selects which assistant the visitor chats with.
curl -X POST https://core-api.heysadie.ai/web-chat/session \
-H "Authorization: ApiKey YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "phoneNumber": "+15555550123", "visitorId": "usr_abc123" }'{
"sessionToken": "eyJhbGciOi...",
"expiresIn": 1800
}visitorId is optional: a stable, unique-per-end-user identifier you control (your user id, or a random id persisted in the visitor's cookie/localStorage; 1–128 characters, letters, digits, and . _ : -). Supplying it keeps the conversation continuous across token refreshes and page reloads. Omit it for an ephemeral one-shot session.
Return sessionToken to your browser. The token has a 30-minute TTL (expiresIn seconds); after it expires the browser must request a fresh token from your backend.
Send messages (browser)#
The browser authenticates with the session token as a Bearer token — no API key involved. The visitor identity is sealed inside the token and cannot be spoofed from the browser.
const res = await fetch("https://core-api.heysadie.ai/web-chat/messages", {
method: "POST",
headers: {
Authorization: `Bearer ${sessionToken}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ text: "Do you have a table for two tonight?" }),
});
const { reply } = await res.json();text is optional (max 4,000 characters) — omit it or send an empty string to trigger the assistant's opening greeting, which is a good way to start the widget.
{
"reply": "Hi! I'd be happy to help with your reservation. What's your name?"
}End the conversation (browser)#
When the visitor closes the chat, end the conversation explicitly:
await fetch("https://core-api.heysadie.ai/web-chat/end", {
method: "POST",
headers: { Authorization: `Bearer ${sessionToken}` },
});
// -> { "ended": true }Errors#
| Status | Cause |
|---|---|
400 | phoneNumber missing or not E.164 (session endpoint); text over 4,000 characters (messages endpoint) |
401 | Missing, invalid, or expired Authorization header |
404 | Phone number unknown or not assigned to your tenant — returns the bare { "error": "not_found" } body (see Errors) |
502 | Messaging backend returned a non-2xx response |
503 | Messaging backend unreachable |
CORS
The /web-chat/messages and /web-chat/end routes are callable from any origin — the per-request session token is the security boundary, not an origin allowlist. /web-chat/session is deliberately not CORS-exposed, since it must only ever be called server-side.
Web-chat conversations appear alongside other channels in your conversations and fire the messaging webhooks when they start and end.
See the API reference for the full endpoint specification.
New to this? Web chat explains what it does and when to use it, without the API detail.