[PL] API reference, webhooks, and the embeddable widget for Bobโyour governed AI front office.
{
"email": "admin@office16852.com",
"password": "your_password"
}
{
"email": "customer@business.com",
"password": "customer_password"
}
[PL] Three paths: [PL] (1) [PL] Public same-origin anonymous โ POST /api/chat [PL] (e.g. marketing site widget; no login). (2) [PL] Cross-origin embed โ POST /api/widget/chat [PL] with X-Widget-Key [PL] and allowed Origin[PL] . (3) [PL] Authenticated app / Mission Control โ POST /api/chat/session [PL] and POST /api/chat/message [PL] (requires chat.manage [PL] and session/CSRF for cookie auth) โ [PL] not [PL] for anonymous fetch [PL] from public pages.
message, session_id[PL] , optional business_id.
X-Widget-Key, Content-Type: application/json. Origin [PL] must be allowed for the key. See docs/REQUEST_FLOWS.md [PL] in the repository for CORS details.
chat.manage[PL] ). Returns 401 [PL] if called anonymously from a public page โ use POST /api/chat [PL] for that case instead.
{
"session_id": "session_123",
"message": "Hello, I need help with my order"
}
[PL] Add Bob to any website with a single script tag. After onboarding, your widget embed code is available in the Customer Portal under [PL] Widget Setup.
<!-- Paste before </body> --> <script src="https://your-domain.com/widget/loader.js" data-widget-key="YOUR_WIDGET_KEY" data-position="bottom-right" async> </script>
[PL] Personas control how Bob communicates โ tone, name, and system instructions. Every tenant gets a default persona on signup; you can customize it from the Admin Dashboard or the API.
{ name, description, tone, systemPrompt }[PL] Published pricebook is the source of truth. Use the APIs below for live numbers; this table matches pricebook-seed [PL] V1 (adjusts when you publish a new version).
| [PL] Feature | [PL] Starter | [PL] Pro | [PL] Enterprise |
|---|---|---|---|
| [PL] List price (USD/mo) | [PL] $79 | [PL] $249 | [PL] $899 |
| [PL] Included AI credits / mo | [PL] 15,000 | [PL] 75,000 | [PL] 250,000 |
| [PL] Team seats | [PL] Up to 3 | [PL] Up to 10 | [PL] Unlimited |
| [PL] Standard integrations (included) | 1 | 3 | 10 |
| [PL] Support | [PL] Email | [PL] Priority | [PL] Dedicated |
[PL] Use the block that matches your scenario. Do not copy the admin example into anonymous marketing HTML.
const response = await fetch('/api/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
session_id: sessionId,
message: userMessage,
business_id: 'office16852-platform'
})
});
const data = await response.json();
const response = await fetch('https://office16852.com/api/widget/chat', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Widget-Key': 'pk_live_...',
'Origin': 'https://your-customer-site.com'
},
body: JSON.stringify({ session_id: sessionId, message: userMessage })
});
// JavaScript โ requires logged-in admin / Mission Control (Bearer)
const response = await fetch('/api/chat/message', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + token
},
body: JSON.stringify({
session_id: sessionId,
message: userMessage
})
});
const data = await response.json();
// Python โ authenticated only
import requests
response = requests.post(
'https://office16852.com/api/chat/message',
headers={
'Content-Type': 'application/json',
'Authorization': f'Bearer {token}'
},
json={ 'session_id': session_id, 'message': user_message }
)