Keys & domains
Embeds run in your visitors’ browsers, so their API key is visible to anyone who views source. That is expected and safe — provided you use a publishable key and restrict it to your domains.
Never put a secret key in an embed. Secret keys carry full permissions and are meant for servers you control. If you have pasted one into a web page, revoke it in the dashboard now and create a publishable key instead.
Creating the key
In the Ullr dashboard: Integrations → API keys → Create key.
- Type: Publishable
- Scopes: see the table below
- Allowed domains: your site’s hostnames
You can also create a key from any embed’s configurator page, which pre-selects
the “All embeds” preset — trails:read, lifts:read, features:read,
resorts:read and updates:read. That preset deliberately contains live-status
scopes only: no history, no snapshots.
Publishable keys remain visible in the dashboard after creation, so you can re-copy a snippet any time.
Scopes each embed needs
| Embed | Scopes |
|---|---|
| Trail list | trails:read, resorts:read |
| Lift list | lifts:read, resorts:read |
| Interactive map | resorts:read + one per layer: trails:read, lifts:read, features:read |
| Conditions widget | resorts:read, updates:read + one per layer |
One key can serve every embed on your site. Give it the union of what those embeds need and nothing more.
Do not add history scopes (trails:readHistory, lifts:readHistory,
features:readHistory) or the snapshot and summary scopes to an embed key. No
embed uses them, and they expose your operational record over time to anyone
who copies the key out of your page.
Restricting domains
An unrestricted publishable key works from anywhere — including someone else’s website, on your data and your quota. Set the allowed domains.
Enter bare hostnames, one per entry:
example.com
*.example.com- No scheme, port or path.
https://example.com/is invalid; useexample.com. - One leading wildcard label is allowed.
*.example.commatcheswww.example.comandconditions.staging.example.com, but not the bareexample.com. List both when you need both. - Localhost is always allowed —
localhost,127.0.0.1and[::1]on any port — so local development needs no extra entry. - An empty list means no restriction. Fine while prototyping; fix it before you ship.
Matching is against the browser’s Origin header. A request with a restricted
key and no Origin at all — plain curl, most server-side code — is denied.
That is deliberate: publishable keys are for browsers.
Rotating a key
- Create the new key with the same scopes and domains.
- Update your pages to the new key and deploy.
- Watch Last used on the old key in the dashboard — it stops advancing once nothing is using it. (It updates at most once an hour, so give it time.)
- Delete the old key.
If a key has leaked and you need it dead immediately, revoke it — that takes effect at once, and you can create the replacement afterwards.
What a rejected embed looks like
An embed whose key is refused renders nothing rather than an error box, so check the browser’s network tab:
| Status | Cause |
|---|---|
401 | Key missing, misspelled, revoked, or expired |
403 | Key lacks the scope for that data, or your domain is not on its allowed list |
Troubleshooting walks through each case.