# Developers & agents

> Run your phone system from a terminal or an AI agent with the rinzo command-line tool.

## What the CLI does

The `rinzo` command-line tool manages phone-system configuration alongside the [Control panel](https://app.rinzo.ai/), from a terminal, a script or an AI agent: your AI receptionist and the business information it answers from, people and extensions, desk phones and softphones, phone numbers, call routing, voicemail, ring groups, call history and webhooks to your other systems. It uses the same API as the Control panel (`https://api.rinzo.ai/v2`), so everything it does shows up there and stays editable there. First [sign up](https://signup.rinzo.ai/); you need to be an administrator of the account.

## Have an agent set it up

To have an AI agent such as Claude Code or Codex set up Rinzo for you from the start, give it one line:

`Set up my business phones with Rinzo. Follow https://rinzo.ai/SKILL.md`

The [setup playbook](https://rinzo.ai/SKILL.md) follows your authorization for installation and changes, asks you to approve its sign-in when needed, consolidates only missing details, then builds and tests within your scope. See [Agents](https://rinzo.ai/agents.md) for who does what. The rest of this page is the reference for doing it yourself.

## Install

Python 3.10 or newer; nothing else.

```
curl -fsSL https://rinzo.ai/install.sh | sh
```

The script downloads the CLI from this site, checks its SHA-256 and installs it with uv, pipx or a private Python environment, putting `rinzo` in `~/.local/bin`. To install by hand, download the [CLI 0.17.0 wheel](https://rinzo.ai/downloads/rinzo-0.17.0-py3-none-any.whl) and [SHA256SUMS](https://rinzo.ai/downloads/SHA256SUMS) into one folder, then:

```
sha256sum -c SHA256SUMS
uv tool install ./rinzo-0.17.0-py3-none-any.whl     # or: pipx install ./rinzo-0.17.0-py3-none-any.whl
```

## Log in

Run `rinzo login`. The CLI shows a link and a short code and opens your browser at the Control panel’s sign-in for the CLI. Sign in as an account administrator (or confirm, if you are already signed in), check that the code matches and click Approve. The CLI then receives your account’s API key directly from Rinzo and keeps it in your computer’s keychain (macOS Keychain, or GNOME Keyring or KWallet on Linux); where there is no keychain it goes in a file only you can read. It exchanges the key for a one-hour session as needed. `rinzo whoami` shows the account in use and `rinzo doctor` checks the whole chain.

```
rinzo login
rinzo whoami
```

| Situation | Command |
| --- | --- |
| An AI agent | `rinzo login --start`, show the person the link, then `rinzo login --wait --timeout 100`; exit code 4 means still waiting, so run it again |
| Username and password instead of a browser | `rinzo login --password` (an administrator’s sign-in: other users can change only their own profile) |
| CI or a container | set `RINZO_API_KEY` from your secrets manager, or pipe the key to `rinzo login --api-key-stdin` |
| Several accounts | `rinzo login --profile acme`, then `--profile acme` on any command |

## What the key can do

It is your account’s own API key: it can do everything an account administrator can do in the Control panel, for as long as it exists. Keep it like a password. `rinzo logout` removes it from this computer only; `rinzo auth rotate-key --yes` issues a new key and stores it here, and every other copy stops working at once. That is how to revoke access.

## Give an AI agent the skill

The CLI carries a skill for AI agents, `rinzo`. It teaches the safe way to work (discover and plan internally, follow your authorization, read changes back and check routing with simulated calls; verify real calls when authorized and possible, otherwise report them pending), a workflow for building an AI receptionist from your business information, and step-by-step recipes: a new employee, a main number with an auto-attendant and office hours, ring and hunt groups, forwarding, shared voicemail, a conference bridge, blocked callers, call recording, call events to a CRM and offboarding.

```
rinzo skill install                 # Claude Code
rinzo skill install --agent codex   # Codex (or --agent all, or --dir DIR)
```

The bundled skill matches the CLI version. After a CLI upgrade, run the install command again to refresh your agent’s copy. Local edits are preserved; back them up before choosing `--force`. You can also [read the skill](https://rinzo.ai/agents/rinzo/SKILL.md) here. Agents that speak the Model Context Protocol can use the CLI as a tool server instead of a terminal: `claude mcp add rinzo -- rinzo mcp` (Cursor and Claude Desktop take the same command in their MCP settings). Every command becomes a typed tool under the logged-in profile, with read-only and destructive tools marked, and the skill is served as resources.

## Commands

`rinzo COMMAND --help` describes every option and `rinzo schema` lists every command as JSON. For a smaller response, use `rinzo schema users create` or `rinzo schema auto-attendant`; no login is needed. The installed schema describes the installed version.

| Command | What it manages |
| --- | --- |
| `receptionists` | AI receptionists: `apply --spec FILE` (try `--dry-run` first), `show`, `validate`, `publish --idempotency-key KEY`, `attach --number EXTENSION`, `access`, `activate`, `sessions`, `directory`; see AI receptionist below |
| `knowledge`, `ai-jobs` | what a receptionist answers from: `import-site --key --name --url` (Rinzo reads the business's public website and writes Markdown notes), `create --key --name`, `upload --file` (PDF, Word, text or Markdown), `preview`; `ai-jobs wait ID --timeout 600` until an import or file is processed |
| `users` | people: `create --first-name --last-name --email --extension auto --invite`, `invite`, `forward --to NUMBER` (the number rings instead of their phones; `--with-phones` rings both; `--failover` only when a phone is offline), `delete --yes` |
| `devices` | phones: `create --name --owner USER --type sip_device\|softphone\|cellphone` (`--credentials-file PATH` keeps the SIP password in a file only you can read), `credentials ID`, `status` |
| `trunks` | optional PBX/SIP application connections: `list`, `create --name --auth password\|ip`, `credentials ID --credentials-file PATH`, `status`, `calls ID`, `update`, `rotate-password\|delete --yes`. See [SIP Trunking](https://rinzo.ai/docs/sip-trunking.md) |
| `numbers` | `list` (and where each one rings), `assign NUMBER --user\|--callflow\|--trunk`, `release NUMBER --yes`. During early access, new numbers are added on request (email [support@rinzo.ai](mailto:support@rinzo.ai)): `buy` is refused for customer accounts |
| `ring-groups` | `create --name --member ID` (repeat `--member`; `--member ID,delay=20,timeout=15` adds a backup person who rings later; `--strategy single` rings one after another; `--overflow` sends unanswered calls to a voicemail box, another group, a person or a number), `update GROUP_ID` (members and their timing, strategy, ring time, overflow), `list`, `delete --yes` |
| `auto-attendant` | a main number from one spec: greetings, office hours, lunch, holidays (Good Friday and “the Monday before May 25” too) and menus, with a key that plays a message and starts over. `create --spec FILE` (try `--dry-run` first), `show`, then `update` with the spec it shows, `delete --yes` |
| `calls` | `list --since 24h` (call history), `active` (calls in progress) |
| `voicemail` | boxes: `create --name --notify EMAIL --extension auto` (a shared box gets a PIN for checking it by phone; `--pin-file PATH` saves it to a file only you can read), `messages BOX`, `message BOX MSG --download FILE` |
| `conferences` | conference rooms: `create --name --pin-file PATH` (the room, its extension and a PIN; people join able to talk) |
| `extensions` | `--from 1200 --count 7`: every extension and mailbox in use, and the next free numbers |
| `callflows` | call routing. `simulate NUMBER --at TIME --keys 1` shows what a call would do, step by step, without dialling: which hours apply, what the menu does, who rings and for how long, where it ends. Repeat `--at` and `--keys` to check a whole schedule at once |
| `menus`, `rules` | the menus, office hours and holidays an auto-attendant is built from |
| `media` | greetings: `create --name --file greeting.wav` (checks the audio arrived), `get ID` (shows it) |
| `webhooks` | call events to your systems: `available`, `create --name --uri --event` |
| `recording`, `recordings` | call recording: `recording enable --number +1… \| --user ID` turns it on (a number gets a recording notice first; `--no-notice` skips it), `status`, `disable`; `recordings list --since 7d`, `get ID --out FILE`, `delete ID --yes` for what was kept. Recordings are kept 90 days. |
| `account`, `balance` | account settings; your calling credit (read only) |
| `api METHOD PATH` | any other API call, relative to your account (`rinzo api GET limits`) |
| `feedback` | `bug` or `feature`: report a problem or a missing feature to Rinzo (`--last-error` attaches the last failure) |

Every resource has `list`, `get ID`, `create`, `update ID` and `delete ID --yes`. `create` and `update` take a JSON document (`--data FILE`) or single fields (`--set key=text`, `--set key:=json`); `update` merges your changes into the current document. `users create`, `devices create` and `ring-groups create` set things up exactly as the Control panel’s SmartPBX does, so the result looks and behaves the same there. Ordinary resource reads hide voicemail PINs and SIP passwords unless you add `--show-secrets`. Raw `api` output and phone-credential commands can expose secrets.

## Examples

A new employee with an extension, voicemail, a desk phone and their mobile ringing too:

```
rinzo users create --first-name Jane --last-name Doe --email jane@example.com --extension auto --invite
rinzo devices create --name "Jane desk phone" --owner USER_ID
rinzo devices create --name "Jane mobile" --owner USER_ID --type cellphone --number +16045551234
```

A sales line that rings two people, on its own number:

```
rinzo ring-groups create --name Sales --member USER_1 --member USER_2
rinzo numbers assign +16045550123 --callflow CALLFLOW_ID
```

A front desk that rings two people for 20 seconds, then the manager for 15 as backup, then voicemail:

```
rinzo ring-groups create --name "Front desk" --member TOM --member LENA --member PRIYA,delay=20,timeout=15 --overflow voicemail:BOX_ID
```

A main number with office hours, lunch, holidays and a menu, then what a caller gets on Christmas morning and when pressing 2 on a Tuesday:

```
rinzo auto-attendant create --spec main-number.json
rinzo callflows simulate +16045550123 --at "2026-12-25 10:00"
rinzo callflows simulate +16045550123 --at "2026-10-13 10:00" --keys 2
rinzo callflows simulate +16045550123 --at "2026-10-13 07:59" --at "2026-10-13 08:00" --keys 1 --keys silence
```

Yesterday’s calls, and call events sent to a CRM:

```
rinzo calls list --since 24h
rinzo webhooks create --name CRM --uri https://crm.example.com/rinzo --event channel_destroy
```

`devices create` prints the phone’s SIP username and password; the SIP domain is your account realm and the outbound proxy is `sip.rinzo.tel`. See [Phones & devices](https://rinzo.ai/docs/phones.md).

## AI receptionist

The AI receptionist answers callers from your business information (facts, instructions and documents you upload), puts them through to people, ring groups, voicemail or an outside number, reaches anyone in your phone directory by name or extension, and takes messages, which arrive as voicemail with a written summary. It books appointments only when the account has connected a Google Calendar and the receptionist has a booking policy; otherwise it takes the request as a message for your team to confirm. You can set it up in the Control panel (SmartPBX › AI answering) or with the CLI. One JSON spec describes a receptionist: greeting, instructions, documents, where callers go when they ask for a person, and the fallback.

```
rinzo receptionists apply --spec receptionist.json --dry-run   # what it would do, and missing information
rinzo receptionists apply --spec receptionist.json             # uploads the documents, saves the draft
rinzo receptionists publish ai-receptionist-front-desk --idempotency-key publish-front-desk-001
rinzo receptionists access                                     # is AI answering on for the account?
rinzo receptionists attach ai-receptionist-front-desk --number 1000 --dry-run
```

`apply` never publishes or changes call routing; `publish` and `attach` do, so the skill does them only within your authorization. Put it on an extension first, call it yourself, then on the main number or an after-hours branch. `rinzo callflows simulate NUMBER --ai-outcome human` traces where its branches lead without running it; there is no command that tests the conversation yet, so a real call is the test. `rinzo receptionists sessions` shows how calls ended and which messages were delivered, never what was said: a transcript is kept only when `retention.store_transcript` is on, and the audio only when `retention.store_audio` is (then the greeting should say the call is recorded). `summary_recipients` get one email per call. `language` is English, Spanish or French (one per receptionist, one voice). With `tools` in the spec (up to five HTTPS lookups against your own systems, such as an order status by number), the receptionist can fetch a live answer during the call; `rinzo receptionists tools test ID TOOL --arg order_number=A100` shows what it would say, and the request headers you store (an API key, say) are never printed back. The [receptionist reference](https://rinzo.ai/agents/rinzo/references/receptionists.md) has the spec, documents, schedules, lookups and recovery.

### Start from an industry template

The CLI ships ready-made receptionists for common kinds of business (plumbing and heating, a dental clinic, a cleaning service, property management and others): a greeting, instructions, the facts and documents that business’s callers ask about, the destinations it needs and, where the trade answers differently when closed, an after-hours variant. A template renders to the same spec and knowledge files, so nothing changes in how a receptionist is checked, published or routed.

```
rinzo receptionists templates                                   # the catalogue: id, group, summary, variables
rinzo receptionists template plumbing-heating --out ./northshore --set business_name="Northshore Plumbing & Heating" --set office_hours="Mon-Fri 7-6" --set dispatch=ring-group:ID --set office_voicemail=voicemail:ID
```

`template` writes `receptionist.json` (and `after-hours.json` when the template has one) and the knowledge documents, then lists what the business still has to supply: values left at their example, every `[FILL IN: …]` marker in the documents, and a missing website. A template is a starting point, not a promise about how that business’s calls go: replace every marker with the business’s own facts (never invented ones) before `apply`, and test it with a real call as above. The catalogue is also published as [/agents/templates/index.json](https://rinzo.ai/agents/templates/index.json), with each template’s files under `/agents/templates/ID/`.

## Output, errors and exit codes

At a terminal the CLI prints tables; in scripts and agents it prints JSON (force either with `--json` or `--table`), never your session token. Errors, including bad arguments, are JSON when stderr is not a terminal, with the reason and, for invalid data, each rejected field. Exit codes: 0 ok, 1 error, 2 bad usage, 3 not logged in, 4 login still waiting for approval.

## Safety

Reading is free. Deleting anything, and releasing a phone number, needs `--yes`; the skill requires authorization covering the action; explicit or standing approval within your limits counts, and `--yes` is not permission by itself. The plan includes one phone number; each extra number costs $5 a month from your credit. Credit, cards and top-ups are managed only in the Control panel under [My Account › Billing](https://app.rinzo.ai/#/billing); the CLI only reads your balance and never handles card details. 911 and emergency calling are not supported. A change that timed out may still have happened, so the CLI never repeats one by itself: read it back first. Webhook and call-recording addresses must be public HTTPS URLs.

## Feedback from agents

Agents send reports of problems and missing features only when your authorization covers external sends; read-only or per-change approval limits also apply to feedback. Otherwise they prepare the report without sending. The skill tells them when to report and to tell you afterwards. Failures after configuration is opened are recorded with secret values removed (usage errors may have no saved record), and `--last-error` attaches it; failures that look like Rinzo’s fault print a ready-made report command. `--dry-run` shows exactly what would be sent. Reports carry your account when a working login is available; otherwise they are anonymous. Remove personal data from the report before sending it.

```
rinzo feedback bug --last-error --title "ring-groups create answers 500" --details "Sales group with 3 members"
rinzo feedback feature --title "Buy numbers from the CLI" --details "Needed a second 604 number"
```

## How browser login works

`rinzo login` follows the standard device-login pattern (OAuth device authorization, RFC 8628). The approval page lives on the Control panel’s own address and approves only administrators of the account. The key is read with the approving administrator’s own session, held in memory for at most ten minutes, handed to the waiting CLI once and then forgotten. The page shows which computer asked: approve only a login you started yourself.

## Upgrading from the topaz CLI

Rinzo was called Topaz, and its CLI was the `topaz` command (package `topaz-tel`). Remove the old package, which leaves your login and settings in place, then install the Rinzo CLI:

```
uv tool uninstall topaz-tel        # or: pipx uninstall topaz-tel
curl -fsSL https://rinzo.ai/install.sh | sh
rinzo whoami
rinzo skill install
```

The install script also removes a uv or pipx install of `topaz-tel` by itself. On first use `rinzo` copies your login from the topaz CLI (its settings folder and its keychain entry, which both stay as they were), moves a login on the old default API address to the new one, and accepts the old `TOPAZ_…` environment variables until you rename them `RINZO_…`. `rinzo skill install` replaces the `topaz-tel` skill the topaz CLI installed. The `topaz` command keeps working for now as an alias of `rinzo`, with a notice on stderr. [The full CLI guide](https://rinzo.ai/llms-full.txt) has the details.

## Accounts and billing

A person starts the account's free month at https://signup.rinzo.ai/, entering a card on Stripe's hosted checkout (nothing is charged that day; the month-to-month plan follows unless they cancel). They manage the plan, calling credit and the card in the Control panel under My Account › Billing (https://app.rinzo.ai/#/billing), in Stripe's own forms. An agent may share those links but must never enter, request or handle card details, and signup and card billing stay with the person. Number requests must fit the person's explicit or standing authorization and limits.

## Machine-readable files

[Setup playbook](https://rinzo.ai/SKILL.md) · [LLM index](https://rinzo.ai/llms.txt) · [Full CLI guide](https://rinzo.ai/llms-full.txt) ·[Agent skill](https://rinzo.ai/agents/rinzo/SKILL.md) · [CLI schema](https://rinzo.ai/agents/cli-schema.json) · [Kazoo API callback catalog](https://rinzo.ai/agents/native-catalog.json) · [Receptionist templates](https://rinzo.ai/agents/templates/index.json) · [Install script](https://rinzo.ai/install.sh) · [Release manifest](https://rinzo.ai/downloads/manifest.json). The schema is what `rinzo schema` prints. The templates index is what `rinzo receptionists templates` prints, with each template’s `template.json` and knowledge documents under `/agents/templates/ID/`. The callback catalog lists the Kazoo API modules Rinzo is built from, with source hashes; it is reference material, not a promise that every endpoint is available to your account. Every page on this site is also Markdown: add `.md` to its address ([this page](https://rinzo.ai/docs/developers-agents.md)) or send `Accept: text/markdown`.

---

The Markdown version of https://rinzo.ai/docs/developers-agents/. An index of every page: https://rinzo.ai/llms.txt. 911 and emergency calling are not supported during early access.
