Authentication
Tavio supports two authentication methods for API access and one for embeddable widgets. All API requests must be authenticated.
API Key Authentication
Every tenant receives an API key from the Settings page. Pass it in one of two headers:
Authorization: Bearer YOUR_API_KEYx-api-key: YOUR_API_KEY
cURL
bash
curl -X POST https://bankmind.aihookd.site/api/chat \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"message": "What are your loan rates?"}'JavaScript (fetch)
javascript
const res = await fetch("/api/chat", {
method: "POST",
headers: {
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({ message: "What are your loan rates?" }),
});
const data = await res.json();
console.log(data.response);Widget Token Authentication
The embeddable web widget uses HMAC-signed base64url tokens instead of raw API keys. This prevents key exposure in client-side code.
Token format: tenantId:channelId:nonce:signature (base64url-encoded). Tokens are generated server-side and verified on every widget request.
Token generation (server-side)
typescript
import { generateWidgetToken } from "@/lib/widget-token";
const token = generateWidgetToken({
tenantId: "tenant_abc123",
channelId: "channel_widget_001",
});
// Pass this token to your frontend widget scriptWidget embed with token
html
<script
src="https://bankmind.aihookd.site/widget.js"
data-key="BASE64URL_WIDGET_TOKEN"
data-position="bottom-right"
defer
></script>Rate Limiting
All API endpoints are rate-limited to protect the platform:
| Limit | Value |
|---|---|
| Requests per window | 120 |
| Window duration | 60 seconds |
| Rate limit response | 429 Too Many Requests |
When rate-limited, wait for the window to reset before retrying. The response includes a Retry-After header.
Error Responses
Authentication failures return structured JSON errors:
401 Unauthorized
json
{
"error": "Invalid or missing API key",
"code": "AUTH_INVALID"
}429 Rate Limited
json
{
"error": "Rate limit exceeded. Try again in 42 seconds.",
"code": "RATE_LIMIT"
}