# SDKs and the CLI

> Pick an official client library for Ruby, PHP, Node or Python, or script Broadcast from a terminal with the broadcast CLI.

Source: https://sendbroadcast.net/university/developers/sdks-and-cli

You can call the Broadcast API with `curl`, and the earlier lessons did. For real code, an official library saves you from mistakes that are easy to make and hard to notice. In this lesson you choose between the SDKs and the CLI, and learn the behaviour they all share.

## Four official libraries

There are official libraries for four languages, and each covers every API operation:

- **Ruby**: the `broadcast-ruby` gem. It includes an ActionMailer delivery method, so existing Rails mailers can send through Broadcast.
- **PHP**: `broadcast/broadcast-php` on Packagist, PHP 8.1 or later.
- **Node and TypeScript**: `@send-broadcast/sdk` on npm, Node 18 or later, fully typed.
- **Python**: `broadcast-python` on PyPI, Python 3.9 or later, with no dependencies.

For any other language, call the REST API directly, or generate a client from your installation's OpenAPI spec at `/api/v1/openapi`.

## A first call with the Node SDK

```bash
npm install @send-broadcast/sdk
```

```ts
import { Broadcast } from '@send-broadcast/sdk';

const client = new Broadcast({
  apiToken: process.env.BROADCAST_API_TOKEN,
  host: 'https://broadcast.example.com',
});

await client.subscribers.create({ email: 'ada@example.com', first_name: 'Ada' });
```

The other libraries follow the same shape. Each has a guide: [Ruby](/docs/ruby-sdk), [PHP](/docs/php-sdk), [Node](/docs/node-sdk) and [Python](/docs/python-sdk).

## What every library does the same way

The four libraries share one contract. Learn it once and it holds in every language.

**`host` is always required.** Broadcast is self-hosted, so every installation has its own domain. No client guesses one.

**Warnings are surfaced.** A successful write can still report that it ignored part of your request, such as a misspelled field. Every client exposes these warnings, and can be set to raise an error on them. In tests, turn that on.

**Retries are bounded and selective.** Timeouts, `429` and `5xx` responses are retried with backoff, and `Retry-After` is honoured up to a ceiling. A `422` is never retried: the same request fails the same way.

### Retried with backoff

- Timeouts
- `429`
- `5xx`

### Never retried

- `422`: the same request fails the same way

A retry only helps when the next attempt can give a different answer.

**Masked credentials are never written back.** The API returns credential fields masked with bullets. If you read an email server and write it back unchanged, a naive client would replace your SMTP password with bullets. Every client strips masked values from updates and warns you instead.

### A naive client

- Reads the server: password is bullets
- Writes it back
- The password is now bullets

### An official library

- Reads the server: password is bullets
- Strips masked values before it writes
- The password is unchanged

The same read and write, with and without the protection.

**Redirects are not followed.** Every request carries your token. A redirect to another host would hand the token over, so the clients refuse. A redirect almost always means `host` is wrong.

**Webhook verification is built in.** Each library verifies webhook signatures with HMAC-SHA256, a five-minute tolerance and a constant-time comparison. The webhooks lesson explained why each step matters.

## The broadcast CLI

The `broadcast` CLI is a single bash script that wraps the API. It needs only `curl`, and `jq` if you have it. Your own installation serves it. The exact install command is on the **Agents** page in your dashboard:

```bash
curl -fsSL https://broadcast.example.com/agents/install | bash
broadcast login --token=YOUR_API_TOKEN --host=https://broadcast.example.com
broadcast whoami
```

Use a **channel** token. The CLI does not send `broadcast_channel_id`, which admin tokens require. `login` saves the credentials to `~/.config/broadcast/config` with owner-only permissions.

A few commands show the pattern:

```bash
broadcast status
broadcast subscribers find --email=ada@example.com
broadcast subscribers tag --email=ada@example.com --tag=vip
broadcast broadcasts create --subject="Weekly update" --body="<p>Hello</p>"
broadcast broadcasts stats 42
```

Output is JSON, which suits scripts. When `jq` is installed, the CLI pretty-prints it. Exit codes tell a script what went wrong: `1` authentication, `2` not found, `3` validation, `4` any other error, such as a rate limit or a server error.

`broadcast prime` prints everything your token can do: permissions, channel status, endpoints and rate limits. For anything without its own command, `broadcast api METHOD PATH` calls any endpoint.

After you upgrade Broadcast, run `broadcast upgrade` to get the matching CLI from your installation.

## Which one to use

- Application code: an SDK.
- A Rails app that already sends mail with ActionMailer: the Ruby SDK's delivery method.
- A one-off script, a cron job or a quick check from a terminal: the CLI.
- An AI agent: the next lesson.

Whichever you pick, give it its own token with only the permissions it needs. Treat that token like a password: anyone who holds it can act as your integration until you revoke it.

## What you learned

- Official SDKs exist for Ruby, PHP, Node and Python, and each requires `host`.
- They all surface warnings, retry timeouts, `429` and `5xx` (never `422`), and protect masked credentials.
- The `broadcast` CLI comes from your own installation and uses a channel token.
- CLI output is JSON by default, with exit codes for scripts.

## Quiz
1. Why must you always pass host to an official SDK?
   - Broadcast is self-hosted, so every installation has its own domain and no default is correct (correct)
   - The host selects the API version
   - The host replaces the API token
   There is no shared cloud endpoint, so the clients refuse to guess a host.
2. Which errors do the SDKs retry with backoff?
   - Every error, including 422
   - Only 401
   - Timeouts, 429 and 5xx, but never 422 (correct)
   - None, retries are up to you
   A 422 is deterministic, so retrying it only adds latency. Timeouts, 429 and 5xx are retried.
3. Which kind of token does the broadcast CLI need?
   - An admin API token
   - A channel API token (correct)
   - Your dashboard password
   The CLI does not send broadcast_channel_id, which admin tokens require, so it uses a channel token.
