Tokens and allowed websites

How the one-use call token works, how to allow your websites, and the limits that apply to web calls.

A web call is safe to start from a browser because of two things: a token that is worth almost nothing if it leaks, and an allow-list of the websites that may use it.

The token

Your server creates a call with POST /v1/calls/web and gets back an access_token. It is not your API key. It is a signed value that already contains everything the call needs: which call, which agent, which organization and which websites may use it. The page cannot change any of that.

Lifetime60 seconds. Request it when the visitor clicks, not in advance.
UseOnce. The first connection spends it; a second is refused with token_already_used.
ScopeOne call, with one agent, in one organization.
UnusedIf a token is never used, the call is closed as failed with disconnection reason web_call_not_started a few minutes later.

The create response also tells you expires_at and expires_in, and which agent_version the call will run.

What the page cannot do

The token decides everything. A page cannot:

  • choose a different agent, or a different organization;
  • change the agent's prompt, voice or tools;
  • change metadata or the dynamic variables, which your server fixed when it created the call;
  • point the call's webhook somewhere else.

Anything else the page sends is ignored.

Allow your websites

Before the first call, list the websites that may start calls: Settings, Web calls in the dashboard, or the API.

curl -X PUT https://api.dialgem.com/v1/web-calls/settings \
  -H "X-API-Key: $DIALGEM_API_KEY" -H "Content-Type: application/json" \
  -d '{ "allowed_origins": ["https://www.example.com", "https://*.example.com", "http://localhost:3000"] }'

An origin is scheme://host[:port] with no path, for example https://www.example.com. Rules:

  • https://*.example.com allows every subdomain, but not example.com itself. List both if you need both.
  • * allows any website. Use it only for a public demo.
  • http://localhost:3000 is fine while developing; remove it before you launch if you do not need it.
  • The scheme and port must match exactly: https://example.com and http://example.com are different origins.

Until at least one origin is listed, creating a call answers 409 web_origins_not_configured. Setting the list replaces the old one.

What the allow-list protects against

A browser always sends its page's origin when it connects, and a page cannot forge it. So the allow-list stops another website from using a token it got hold of. It does not stop someone who already has a token and is not using a browser. That is what the 60 second life and single use are for: a token is spent the first time it is presented, so a copy that leaks is useless the moment the real page connects.

Limits

LimitDefaultWhen it is hit
Calls at once10 per organizationThe next visitor's call is refused with busy.
Calls created60 a minute per organizationMore answer 429 with a Retry-After header. Wait that long before retrying.
BillingLike any other callCreating one answers 402 if the organization cannot pay, and the call is refused at connect if that changed in between.

The two limits protect you as much as Dialgem: a script that hammers your /api/start-call endpoint would otherwise run up your bill. Put your own rate limit and login check on that endpoint.

Next