> ## Documentation Index
> Fetch the complete documentation index at: https://docs.revdesk.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Official SDKs

> Typed TypeScript packages for the RevDesk API and browser calling.

RevDesk ships two official packages so you don't have to hand-roll HTTP calls or wire up browser
audio:

<CardGroup cols={2}>
  <Card title="@revdesk/sdk" icon="code">
    Typed REST client for the v1 API — calls, SMS, phone numbers, caller IDs, caller trust, usage,
    and sub-entities. Types are generated from the OpenAPI spec, so they never drift from the API.
  </Card>

  <Card title="@revdesk/webrtc" icon="phone">
    Browser-calling client. Place and receive calls in the browser through the RevDesk voice
    network, with one branded surface for both connection paths.
  </Card>
</CardGroup>

## @revdesk/sdk

### Install

```bash theme={null}
npm install @revdesk/sdk
# or: bun add @revdesk/sdk
```

### Quickstart

```ts theme={null}
import { RevDesk } from "@revdesk/sdk";

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

// List phone numbers
const { data: numbers } = await revdesk.phoneNumbers.list({ limit: 25 });

// Place an outbound call
await revdesk.calls.dial({ from_number: "+15551230000", to_number: "+15554560000" });

// Send an SMS
await revdesk.sms.send({ from_number: "+15551230000", to_number: "+15554560000", body: "Hi!" });
```

### Pagination

Cursor-paginated endpoints expose `listAll()`, an async iterator that walks every page for you:

```ts theme={null}
for await (const number of revdesk.phoneNumbers.listAll()) {
  console.log(number.phone_number);
}
```

`listAll()` is available on `phoneNumbers`, `subEntities`, and `callerTrust.reputation.numbers`.

### Idempotency

Mutating calls accept an `idempotencyKey` so a retried request is processed once:

```ts theme={null}
import { generateIdempotencyKey } from "@revdesk/sdk";

await revdesk.sms.send(
  { from_number: "+15551230000", to_number: "+15554560000", body: "Hi!" },
  { idempotencyKey: generateIdempotencyKey() },
);
```

### Errors

Every non-2xx response throws a typed `RevDeskError`:

```ts theme={null}
import { RevDeskError } from "@revdesk/sdk";

try {
  await revdesk.calls.dial({ from_number: "+1555…", to_number: "+1555…" });
} catch (err) {
  if (err instanceof RevDeskError) {
    console.error(err.code, err.status, err.message);
    if (err.isRetryable) {
      /* rate-limited or 5xx — safe to retry */
    }
  }
}
```

See [Errors](/api-reference/errors) for the full `RevDeskError` shape.

## @revdesk/webrtc

### Install

```bash theme={null}
npm install @revdesk/webrtc
# or: bun add @revdesk/webrtc
```

Issue the call token server-side with `@revdesk/sdk`, then hand it to the browser client. Both
clients emit the same `callUpdate` / `error` / `ended` events, so your UI doesn't change when you
switch paths. See [Choosing a calling path](/api-reference/calling-paths) for the differences.

### Browser-direct — `RevDeskRTC`

```ts theme={null}
import { RevDeskRTC } from "@revdesk/webrtc";

// token from revdesk.webrtc.getToken({ from_number, to_number })
const call = new RevDeskRTC({ token });
call.on("callUpdate", ({ state }) => console.log(state));
await call.connect();
call.dial({ to: "+15554560000", from: "+15551230000" });
```

### Relay — `RevDeskRoom`

```ts theme={null}
import { RevDeskRoom } from "@revdesk/webrtc";

// from revdesk.webrtc.getRoomToken({ from_number, to_number })
const { token, room_url, call_id } = await revdesk.webrtc.getRoomToken({ from_number, to_number });
const call = new RevDeskRoom({ token, roomUrl: room_url, callId: call_id });
call.on("callUpdate", ({ state }) => console.log(state));
await call.join();
```

<Note>
  Calls fail through the `error` event with a typed `RevDeskCallError` (`code` is one of
  `connection_failed`, `connection_timeout`, `call_rejected`, …).
</Note>
