Authentication
Two ways to authenticate users with Returning.AI widgets, depending on whether you have backend access.
Two Approaches
Access Key Embed
RecommendedYour server exchanges accessId/ accessKey for a short-lived 15-minute JWT. The token is injected into the widget as the embed-token attribute. User identity is signed into the token request server-side, so your credentials and identifier mapping never touch the client.
Requires a backend. Best for production.
Attribute Auth
Pass user identity directly via data-* attributes on the embed script tag. Prefer a stable field like data-customer-id over email when possible. This remains the fallback when you do not have a backend.
No backend required. For teams without server access.
How Access Key Embed Works
A simple three-step flow. Your credentials stay on the server - only a short-lived token reaches the browser.
- 1
Create an access key pair
Go to Community Settings > Integrations > SDK Access in your Returning.AI dashboard and create an SDK access key. The
accessKeyis shown once only, and revocation takes effect immediately for new token issuance. Store theaccessIdandaccessKeyin your server environment variables. - 2
Exchange credentials for an embed token
On each page load, your server calls
POST /v2/api/widget-access-keys/tokenwith your access credentials. You get back a 15-minute JWT. - 3
Inject the token into the widget
Render the widget element with the JWT set as the
embed-tokenattribute. The SDK validates it as an access gate, then continues auth using the signed identity claims from your server-side token request.
// Access Key flow (Node.js)
const response = await fetch(
'https://api-v2.returning.ai/v2/api/widget-access-keys/token',
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
accessId: process.env.RAI_ACCESS_ID,
accessKey: process.env.RAI_ACCESS_KEY,
userIdentifiers: {
'data-customer-id': req.user.customerId,
},
}),
}
)
const json = await response.json()
const embedToken = json.data?.embedToken
// embedToken -> pass as embed-token attributeToken Lifecycle
Embed tokens expire after 15 minutes. How you handle refresh depends on your setup:
| Scenario | Token Refresh |
|---|---|
| Server-rendered pages | Token generated per page load. 15 minutes is plenty for most sessions. |
| SPAs | Re-fetch token on route navigation. Each view gets a fresh token. |
| Long sessions (>15 min) | Listen for rai-error, re-fetch token, update the embed-token attribute, and call window.ReturningAIWidget.reload(). |
Comparison
| Access Key Embed | Attribute Auth | |
|---|---|---|
| Backend required | Yes | No |
| Security | High - server-issued token with identifiers signed server-side | Basic - client-side attributes |
| Integration | Widget SDK with bundle mode and a server-rendered embed-token | Embed Script (widget-loader.js) |
| Best for | Production websites | Teams without backend access |
Never expose your access credentials
When using Access Key Embed, never include your accessId or accessKey in client-side code. Always exchange them for a token on your server. If your credentials are compromised, rotate them from the Returning.AI admin panel.
Implementation Guides
Choose the guide that matches your setup:
Server-verified identity with short-lived JWTs and bundle mode rendering.
Pass identity via data-* attributes. No backend needed.
Looking for legacy approaches? Token Auth and Server Proxy are available in the Legacy section.