Skip to main content
A bounded client token lets your backend hand a calling credential to an untrusted client (a mobile app, a browser, a partner’s device) without shipping your API key and without letting that client call from any number to any number. You mint a token on your server with your API key. The token is restricted to a set of caller-ID (from) numbers and, optionally, a set of destination (to) numbers. The client uses the token in place of your API key — on the same Authorization: Bearer header — and can only place calls within those bounds. The token is a short-lived, signed rdc_… string; it carries no secret you’d mind a client holding, and it expires on its own.
This is the delegation layer on top of the per-call security already described in the WebRTC security model. Each call placed with a bounded token is still scoped, attributed, and guardrail-bounded — the token simply guarantees the client can’t step outside the from/to numbers you chose when you minted it.

How it works

Mint a token (server side)

import { RevDesk } from "@revdesk/sdk";

const revdesk = new RevDesk({ apiKey: process.env.REVDESK_API_KEY! });

const { data } = await revdesk.clientTokens.create({
  from_numbers: ["+15551234567"],      // caller IDs the client may present (numbers you own)
  to_numbers: ["+15557654321"],        // optional: destinations the client may dial
  ttl_seconds: 900,                    // optional: 60–3600, default 900
  // scopes: ["voice:webrtc"],         // optional: subset of this key's scopes
});

// data.token  -> "rdc_…"   hand this to your client
// data.expires_in, data.from_numbers, data.to_numbers, data.scopes
Requires the tokens:mint scope on your API key. A minted token cannot mint further tokens.

Use the token (client side)

Construct the SDK (or the @revdesk/webrtc browser SDK) with the minted token in place of your API key — nothing else changes:
import { RevDesk } from "@revdesk/sdk";

const revdesk = new RevDesk({ apiKey: tokenFromYourServer }); // an rdc_… token

// Allowed: from/to are within the token's bounds
await revdesk.webrtc.getToken({ from_number: "+15551234567", to_number: "+15557654321" });

// Rejected with 403: destination outside the token's to-allowlist
await revdesk.webrtc.getToken({ from_number: "+15551234567", to_number: "+15550009999" });

Binding rules

FieldBehavior
from_numbersRequired, at least one. Each must be an active number your organization owns. The token may only present these caller IDs.
to_numbersOptional. When set, the token may only dial these destinations. Empty = any non-emergency destination (within your key’s ceiling).
ttl_secondsOptional, 603600, default 900. Revocation is by expiry — mint short-lived tokens and re-mint as needed.
scopesOptional. Must be a subset of the minting key’s scopes. Defaults to ["voice:webrtc"].

Key-level ceiling

You can also cap an API key itself with allowed caller IDs and allowed destinations (in the dashboard under the key’s settings, or via the key management API). When set, every token minted from that key — and every call the key places directly — must fall within that ceiling. Leave the ceiling blank to allow any number the workspace owns. This lets you, for example, issue one key per customer that is permanently restricted to that customer’s numbers.

Where bounds are enforced

The from/to bounds are enforced on every call-placing endpoint, not just token minting: /v1/webrtc-token, /v1/room-token, /v1/calls, /v1/calls/dial, and /v1/sms/send. A request whose from or to falls outside the credential’s bounds is rejected with 403 before any call is placed.