Widget Token
The Widget Token authenticates the calls the widget makes to /api/widget/* from the shopper's browser. Your server issues it; you inject it into the <script> tag from the CDN.
Header
X-Widget-Token: <token>
Token nature
The token is a Base64 string that encodes shopId:timestamp:HMAC-SHA256. Our backend signs it using your Shop API Key as the secret, which means only we can mint valid tokens. HMAC validation runs on every request: tampering with the string yields 401.
From your JavaScript client's standpoint the token is opaque: pass it as data-token and the widget sends it back as X-Widget-Token on every call. You don't need to verify the signature or inspect the contents — that's the backend's job.
Issuing a token
POST /api/shops/{shopId}/widget-token authenticated with your Shop API Key:
curl -X POST https://api.neuroon.ai/api/shops/$SHOP_ID/widget-token \
-H "X-Shop-API-Key: $NEUROON_API_KEY"
Response (status 200):
{
"token": "c2hvcF9hYmM6MTcxNTAwMDAwMDoxYTJiM2M..."
}
The response body is exactly { "token": string }. It does not include expiresAt — the TTL is fixed at 24 hours from issuance.
Lifetime
- Validity: 24 h (
app.widget.token-validity-seconds = 86400in the backend). - Not renewable: to get a new one, call the same endpoint again.
- Recommended rotation: every 23 h with a 1 h safety margin. Cache the last token plus its issuance timestamp on your server; when more than 23 h have elapsed, call the endpoint again before the next render.
HTML injection
Server-side (any framework: Next.js, Razor, PHP, Express, Rails…):
<div id="neuroon-search"></div>
<script
src="https://cdn.neuroon.ai/widget.js"
data-token="<%= widgetToken %>"
data-container="#neuroon-search"
data-theme="auto">
</script>
Replace <%= widgetToken %> with your template engine's syntax. The token is already cached on your server; you just print it here.
Errors
| Code | Cause | Action |
|---|---|---|
401 Unauthorized with missing header | X-Widget-Token missing | The widget adds it automatically; check data-token is present |
401 Unauthorized with token | Invalid signature or token tampered | Mint a new token from your server |
401 Unauthorized after 24 h | Token expired | Call the issue endpoint again |
403 Forbidden with origin mismatch | Browser calls from a domain that does not match shop.url nor app.widget.allowed-origins | Add the domain to the shop or verify it |
Best practices
- Never expose the Shop API Key in the browser. That key is server-only and grants far more capabilities than the Widget Token.
- Do not reuse the same Widget Token between Production and Development. They are signed with different secrets.
- Store tokens encrypted in your stack's secret manager (AWS Secrets Manager, Azure Key Vault, GCP Secret Manager, Vault, encrypted
wp_options, etc.). - Never log tokens to public logs. Treat them as sensitive data.
Next reads
- Recipe · Server-to-server token — full implementations in Node, .NET, Python, PHP.
- Shop API Key — the server-only credential that signs tokens.
- Rate Limits — per-endpoint quotas.
- Errors — codes, structure, field-level errors.