# SDK origins

> Request and review browser origins before web SDK calls reach Thalovant API routes.

Source: https://docs.thalovant.com/developers/sdk-origins/

---
SDK origins is the allowlist for browser apps that call Thalovant from a customer-owned site.

Use it only when a browser runtime must make cross-origin SDK or API requests. For services, agents, CLIs, and jobs, keep using a backend or protected runtime with a secret store.

Free workspaces do not need SDK origins for the starter voice path. Use Public hubs and Connections first; SDK origins appears when a workspace plan supports browser-origin review.

## How It Works

1. **Open SDK origins** in the dashboard.
2. **Choose the workspace** that owns the browser app.
3. **Request one exact origin** such as `https://app.example.com`.
4. **Wait for review.** A workspace reviewer receives a notification and email.
5. **Use the approved origin.** Browser requests from that origin can use non-credentialed CORS.

An origin must include `https://`, host, and optional port only. Do not include paths, queries, fragments, wildcards, `http://`, or `null`.

## What Approval Allows

| Allows | Does not allow |
| --- | --- |
| Cross-origin API calls from the exact approved origin. | Dashboard cookies or refresh-session flows from customer sites. |
| `Authorization` and `Idempotency-Key` request headers. | CSRF or dashboard-only refresh headers. |
| Browser SDK requests from a known production domain. | Wildcard domains, local files, or origins with paths and query strings. |

  Approval is for browser origin checks only. It does not make hub identities, API tokens, setup links, or broker passwords safe to place in JavaScript served to users.

## Safe Browser Pattern

Use a backend when the browser needs secrets.

  
    A web app calls a small approved API surface with short-lived user auth and no long-lived hub identity in the bundle.
  
  
    Identity creation, identity storage, setup material, broker passwords, refresh sessions, and payment flows stay server-side.
  
  
    Request production, staging, and preview domains separately. Disable origins that no longer serve the app.
  

## Local SDKs and Servers

SDK origins are not the security boundary for code that runs from a laptop, backend service, CI job, room device, or private server.

| Runtime | Use SDK origins? | Safer pattern |
| --- | --- | --- |
| Laptop script or CLI | No | Store the identity file outside the repo and restrict it to the current user. |
| Backend service or job | No | Keep tokens, setup material, and hub identity in a server-side secret store. |
| Thalovant Voice device | No | Use the private setup link or generated install command from Connections. |
| Customer browser app | Yes | Request the exact production, staging, and preview origins separately. |

If a browser app needs a secret operation, put that operation behind your backend and call the backend from the browser.

## Notifications

When an origin is requested, the requester and reviewer see a security notification. Email is also sent so the reviewer can open the dashboard and decide.

When the review is complete, the requester receives a status notification and email. Approved origins start working after the CORS cache refreshes.

## If The Browser Is Refused

| Symptom | Check |
| --- | --- |
| Browser preflight returns `400` | Confirm the exact origin is approved and uses `https://`. |
| Works in staging but not production | Request the production origin separately. |
| Credentialed requests fail | Use the dashboard only for cookie-based flows; customer origins are non-credentialed. |
| `X-CSRF-Token` is rejected | Remove dashboard-only headers from SDK origin requests. |
| The app was moved to a new domain | Request the new origin, wait for review, then disable the old one. |

## Ready When

The SDK origin is ready when:

- the origin is exact and approved;
- the browser sends only supported headers;
- long-lived secrets stay out of the browser bundle;
- staging and production origins are tracked separately;
- old or unused origins are disabled.
