---
title: Route Inbound Calls to a Browser Client
description: >-
  Ring one specific browser agent on an inbound call with a dial to
  client:<name>, and why that name must match the client's live registration.
summary: >-
  An inbound voice callback dials client:<name> to ring one browser agent. The
  dialled name must be the exact clientName the browser registered under and
  online, or the leg fails instantly.
date: 2026-10-06T00:00:00.000Z
type: guide
---


## Summary

Outbound calling from the browser is the common first step: your server mints a
token, the [browser SDK](/developers/sdks/webrtc) registers, and the agent dials
out. Routing an inbound call *back* to a specific browser agent is the other
half, and it has one rule that trips up almost everyone: you ring a browser
client by its **registered name**, and that name must match exactly.

When a call comes in, your voice callback returns a `dial` to
`client:<name>`. The platform hands that identity to the PBX, which bridges the
caller to wherever that client is currently registered. If `<name>` is not a
client that is registered and online at that instant, the call does not ring at
all — it fails in about a second and is recorded as a missed call.

## Prerequisites

- A claimed number whose inbound routing points at your voice callback URL. See
  [Claim and route a number](/developers/guides/claim-and-route-a-number).
- A browser agent built with [`@sautikit/webrtc`](/developers/sdks/webrtc) that
  registers and can place outbound calls. See
  [Browser calling with WebRTC](/developers/guides/browser-calling-with-webrtc).

---

## The one rule

`client:<name>` is an internal identity, not a phone number. You do **not** build
a SIP URI for it (`sip:…` or `user/..@realm` will be rejected) — you pass the
bare `client:<name>` and let the platform resolve it to the live registration.

The `<name>` you dial must be the exact `clientName` the browser client is
registered under:

- It is the `clientName` returned by `POST /v1/webrtc/token` — the same value you
  set as `client_name` when you mint the token, if you set one.
- It is **case-sensitive** and must match character for character.
- The client must be **registered and online** when the call arrives.

> 
> This is the single most common cause of an inbound call that never rings. If you
> mint a token with `client_name: "hostnali-agent"` but your callback dials
> `client:jeff`, the PBX looks for a registration named `jeff`, finds none, and
> fails the leg in about a second. You will see `Dialing` and `Missed` in the same
> second with no ring time, and `GET /v1/calls/{id}` returns `no_answer` with no
> failure code. Dial the name the client actually registered under.
> 

## Steps

### Step 1: Mint the token with a known client name

Mint server-side with your bearer key and set `client_name` to the identity you
intend to dial. Give each agent a stable, distinct name so you can ring one
agent and not the whole floor.

```ts
// Your backend — POST /v1/webrtc/token with your bearer API key.
const res = await fetch("https://api.sautikit.com/v1/webrtc/token", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${process.env.SAUTIKIT_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    // The identity you will dial as client:<name>. Keep it stable per agent.
    client_name: "hostnali-agent",
  }),
});

const session = await res.json();
// { token, endpoint, protocol, turnServer, clientName, sipProfile, expiresIn }
// session.clientName is the name to dial — "hostnali-agent" here.
```

### Step 2: Register the browser client and handle the incoming call

Hand the whole token object to the browser SDK. The client registers under the
name from the token; once you see `registered`, it is reachable by
`client:<that name>`. Answer inbound calls with the `incoming` event.

```ts
import { Client } from "@sautikit/webrtc";

const client = new Client({
  token: session.token,
  endpoint: session.endpoint,
  protocol: session.protocol,
  turnServer: session.turnServer,
});

client.on("registered", () => console.log("online as", session.clientName));

client.on("incoming", async ({ from }) => {
  if (confirm(`Incoming call from ${from}. Answer?`)) {
    await client.accept();
  } else {
    client.reject("busy");
  }
});
```

### Step 3: Dial the client from your inbound voice callback

On an inbound call, return a `dial` whose `number` is `client:<name>`, using the
same name the agent is registered under. You can greet the caller first and
record the connected leg as usual.

```xml
<Dial callerId="+254709221592" timeout="30" record="record-from-answer"><Number>client:hostnali-agent</Number></Dial>`}
  sdk={`import { sauti } from "@sautikit/node";

res.json({
  actions: [
    sauti.say({ text: "Thank you for calling Hostnali..." }),
    sauti.dial({
      number: "client:hostnali-agent",
      callerId: "+254709221592",
      record: "record-from-answer",
    }),
  ],
});
```

```json
{
  "actions": [
    { "say": { "text": "Thank you for calling Hostnali..." } },
    {
      "dial": {
        "number": "client:hostnali-agent",
        "callerId": "+254709221592",
        "record": "record-from-answer"
      }
    }
  ]
}
```

The caller hears the greeting, then the browser agent rings. On answer the two
legs are bridged and recording starts.

---

## Routing to the right agent in a multi-agent call centre

Because a client is addressed by its registered name, per-agent routing is just a
matter of naming:

- Give every agent a stable, distinct `client_name` when you mint their token
  (for example their user id or extension), and dial that specific name.
- To ring several agents at once and connect the first to answer, fan out with
  `numbers` and `first_answer_wins`:

```json
{
  "actions": [
    {
      "dial": {
        "numbers": ["client:agent-101", "client:agent-102"],
        "callerId": "+254709221592",
        "first_answer_wins": true,
        "record": "record-from-answer"
      }
    }
  ]
}
```

A name in the list that is not currently registered is simply skipped; only
online agents ring.

## Verify

- Watch the registration: the browser logs `online as <name>` on the
  `registered` event. If it never fires, the client is not reachable yet.
- Place a test call to the number. In the call events you should see ring time
  between `Dialing` and the answer — not `Dialing` and `Missed` in the same
  second. An instant miss means the dialled name had no live registration.
- Confirm the name you dialled is byte-for-byte the `clientName` from the token.

## Next steps

- [Browser / WebRTC SDK](/developers/sdks/webrtc) — the full client reference
- [Dial voice action](/developers/voice-actions/dial) — all `dial` parameters
- [Forward calls and fall back to voicemail](/developers/guides/forward-calls-and-voicemail) — number-level routing without a callback
