API keys
Every widget call from a visitor's browser carries an API key. The key authenticates the call to your account; the allowed origins list bound to it authorizes the page that's calling. Both checks happen on every request — no key, no widget.
Creating one
Admin → API keys → ⊕ New key. Give it a label (just for your view — "production", "staging", etc.) and a list of allowed origins.
The full key value is shown once, at creation. We store only a hash of it server-side; if you close that dialog without copying, you cannot retrieve the value later. If you do lose it: delete the row, mint a fresh one, update the script tag.
Key format: cb_live_ followed by random characters. The cb_live_ prefix is human-recognizable so you can tell at a glance that a string is a Wilow key (and not, say, a Stripe key) when grepping your codebase.
Allowed origins
The list of origins that may use this key. The widget loader sends an Origin header with every API call (/widget/config, /widget/conversations/..., etc.); the server compares it to this list and rejects mismatches with 403 Origin not allowed.
Format: scheme + host (+ port if non-default), one per line:
https://example.com
https://www.example.com
http://localhost:3000A few rules that catch people out — same as in embedding:
http://andhttps://are different origins. List the one your site actually serves.- Subdomain matters.
example.comandwww.example.comare different. - No wildcards yet. Each subdomain explicitly.
- Trailing slash doesn't matter — we strip it.
Edit the list later via API keys → ⋯ → Edit origins. Changes apply server-side immediately; the browser re-sends the Origin header on every request anyway, so the gate runs at request time on every call — not from cached state.
Rotating a key
You'll want to rotate when:
- You suspect leak (committed to a public repo, posted in a screenshot, ex-employee retained access).
- You hit a milestone where rotation hygiene matters (annual review, compliance audit).
- You've never done it on this key and the key is months old.
The cleanest rotation:
- Mint a new key (same allowed origins).
- Update the script tag on every site using the old key. Re-deploy.
- Wait an hour, watch the Usage page. If the new key is taking traffic and the old one isn't, you're safe.
- Delete the old key. Any visitor still on a stale page version sees one failed
/configcall and the bubble doesn't render — that's the cost of rotation.
If the old key is compromised and you can't wait, swap step 4 to come right after step 2 — accept the brief outage on cached pages over the bigger risk of leaving the leaked key valid.
Pitfalls
- Allowed origins isn't optional. A key with no origins listed is rejected on every call. The UI prevents creating one in this state, but if you somehow clear the list later, your widget goes dark until you add one back.
What to monitor
The Usage page shows per-key request volume. Worth a look once a month even if everything's fine — anomalies (a sudden surge from one key) are usually either a viral page or a misbehaving integration.
If a key is drawing traffic from origins you don't recognize, that's worth a closer look. We log every rejected origin too — if you ever need that log, email support.