Skip to content

Command line

The rhino-relay command calls the API for you. It takes the same JSON bodies, prints the JSON response, and exits with a code that says what happened. Its commands are generated from the same OpenAPI document as the API reference, so every endpoint you call with an API key has one.

You need Node.js 20 or later.

Terminal window
npm install -g rhino-relay-cli
rhino-relay --version

Create a key on the console’s API keys page, or with the API (see Authentication). Then save it:

Terminal window
rhino-relay configure --api-key ek_...

This writes config.json, readable only by you, to $XDG_CONFIG_HOME/rhino-relay/ (or ~/.config/rhino-relay/), or to %APPDATA%\rhino-relay\ on Windows. To keep the key out of your shell history, pass --api-key - and type or pipe the key on stdin.

In CI, set environment variables instead. They win over the file:

Terminal window
export RHINO_RELAY_API_KEY="ek_..."
export RHINO_RELAY_BASE_URL="https://api.rhinorelay.com/v1"
rhino-relay health get

The base URL defaults to https://api.rhinorelay.com/v1, for accounts in us-east-2. For another Region, run rhino-relay configure --region <region> or set RHINO_RELAY_REGION, which use that Region’s host from the API’s OpenAPI document (see Regions and limits). For your custom API domain, use rhino-relay configure --base-url or RHINO_RELAY_BASE_URL, which win over the Region. RHINO_RELAY_CONFIG points the command at another config file.

Check it worked: rhino-relay health get prints your account’s health as JSON and exits 0.

Every command is rhino-relay <group> <action>, then the resource ID when the endpoint has one, then flags:

  • Query parameters are flags: --limit 50, --status subscribed, --by stage.
  • --data (or -d) is the request body: JSON text, @file.json to read a file, or - to read stdin.
  • --all, on list commands, follows nextCursor and prints every page as one {"data": [...]}. See Pagination.
  • --idempotency-key sets the Idempotency-Key header. Commands whose endpoint needs one, such as campaigns schedule, make a new key when you don’t give one. Give your own to retry safely; see Idempotency.
  • --if-match <version> sends If-Match, so an update fails with 412 if someone changed the resource since you read it.
  • --compact prints the JSON on one line.

rhino-relay help lists the groups, rhino-relay contacts help lists a group’s actions, and rhino-relay contacts list --help lists an action’s flags.

Terminal window
rhino-relay contacts create --data '{"email":"ada@example.com","consent":{"source":"signup-form","at":"2026-10-01T09:00:00Z","method":"single_opt_in"}}'
rhino-relay contacts lookup --data '{"email":"ada@example.com"}'
rhino-relay contacts list --status subscribed --limit 50
rhino-relay contacts list --tag customer --all
rhino-relay contacts get ct_...
rhino-relay contacts update ct_... --if-match 3 --data '{"addTags":["vip"],"fields":{"firstName":"Ada"}}'
rhino-relay contacts batch --data @contacts.json
rhino-relay contacts delete ct_...
Terminal window
rhino-relay templates create --data @template.json
rhino-relay templates list
rhino-relay templates create-version tp_... --data @version.json
rhino-relay templates render tp_... --data '{"version":2}'
Terminal window
rhino-relay campaigns create --data '{"name":"October news","templateId":"tp_...","templateVersion":1,"segment":{},"stagePlan":{"type":"preset","name":"single"}}'
rhino-relay campaigns test cm_... --data '{"to":["me@example.com"]}'
rhino-relay campaigns schedule cm_...
rhino-relay campaigns schedule cm_... --idempotency-key october-news-1
rhino-relay campaigns report cm_... --by stage
rhino-relay campaigns recipients cm_... --state failed --all
rhino-relay campaigns pause cm_...
Terminal window
rhino-relay imports create-csv --data '{}'
rhino-relay imports list --state dry_run_ready
rhino-relay imports get im_...
rhino-relay imports commit im_... --idempotency-key csv-commit-1
rhino-relay exports create --data '{"kind":"contacts"}'
rhino-relay exports list --kind contacts
rhino-relay exports get ex_...

See CSV import for uploading the file, and Erasure and export for what each export holds.

Terminal window
rhino-relay keys create --data '{"name":"ci","scopes":["contacts:write"]}'
rhino-relay keys list
rhino-relay keys revoke key_...
rhino-relay settings get
rhino-relay settings update --data '{"footerAddress":"1 Main St, Springfield"}'
rhino-relay health get
rhino-relay domains get
rhino-relay domains set --data '{"trackingDomain":"track.example.com"}'

keys create prints the new key’s secret once. Store it then.

Imports, exports, campaigns and setup take a while. --wait <condition> polls until the condition holds, then prints the final response. On a command that starts the work, it follows the response to the resource and polls that. rhino-relay <group> <action> --help lists the conditions a command can wait for, and --timeout <seconds> stops sooner. Each change of state goes to stderr as it happens.

Terminal window
rhino-relay exports create --data '{"kind":"contacts"}' --wait ready
rhino-relay imports commit im_... --wait completed
rhino-relay campaigns schedule cm_... --wait completed --timeout 3600
rhino-relay health get --wait healthy

The conditions come from the API’s OpenAPI document, the same ones a generated client library offers.

A successful response goes to stdout as JSON, indented unless you pass --compact. A 204 response, such as a delete, prints nothing. An error response goes to stderr as the API’s problem JSON, with its code (see Errors). The command never prints your API key.

Exit code Meaning
0 Success (2xx)
1 The API refused the request (4xx): the problem JSON is on stderr
2 The command was wrong: an unknown command or flag, a missing ID, --data that isn’t JSON, or no API key
3 The API failed (5xx), or it couldn’t be reached
4 --wait stopped without its condition: the resource reached a failure state (the response is on stdout), or the wait timed out

In a script, stdout is safe to parse whenever the exit code is 0.

CommandWhat it does
rhino-relay contacts listList contacts (GET /contacts)
rhino-relay contacts createCreate or update a contact (POST /contacts)
rhino-relay contacts batchCreate or update up to 1,000 contacts (POST /contacts/batch)
rhino-relay contacts lookupLook up a contact by email (POST /contacts/lookup)
rhino-relay contacts get <id>Get a contact (GET /contacts/{id})
rhino-relay contacts update <id>Update a contact's fields, tags or email (PATCH /contacts/{id})
rhino-relay contacts delete <id>Erase a contact (DELETE /contacts/{id})
rhino-relay contacts unsubscribe <id>Unsubscribe a contact (POST /contacts/{id}/unsubscribe)
rhino-relay contacts resubscribe <id>Resubscribe an unsubscribed contact with new consent (POST /contacts/{id}/resubscribe)
rhino-relay segments listList segments (GET /segments)
rhino-relay segments createCreate a segment (POST /segments)
rhino-relay segments get <id>Get a segment (GET /segments/{id})
rhino-relay segments update <id>Update a segment (PATCH /segments/{id})
rhino-relay segments delete <id>Delete a segment (DELETE /segments/{id})
rhino-relay segments count <id>Count a saved segment's sendable contacts (GET /segments/{id}/count)
rhino-relay segments count-definitionCount sendable contacts matching a definition (POST /segments/count)
rhino-relay templates listList templates (GET /templates)
rhino-relay templates createCreate a template with its first version (POST /templates)
rhino-relay templates versions <id>List a template's versions (GET /templates/{id}/versions)
rhino-relay templates create-version <id>Add a template version (POST /templates/{id}/versions)
rhino-relay templates get <id>Get a template and its newest 20 versions (GET /templates/{id})
rhino-relay templates render <id>Render a preview (POST /templates/{id}/render)
rhino-relay campaigns listList campaigns (GET /campaigns)
rhino-relay campaigns createCreate a draft campaign (POST /campaigns)
rhino-relay campaigns get <id>Get a campaign (GET /campaigns/{id})
rhino-relay campaigns update <id>Update a draft campaign (PATCH /campaigns/{id})
rhino-relay campaigns delete <id>Delete a draft campaign (DELETE /campaigns/{id})
rhino-relay campaigns test <id>Send test emails (POST /campaigns/{id}/test)
rhino-relay campaigns schedule <id>Schedule a campaign (POST /campaigns/{id}/schedule)
rhino-relay campaigns pause <id>Pause a sending campaign (POST /campaigns/{id}/pause)
rhino-relay campaigns resume <id>Resume a paused campaign (POST /campaigns/{id}/resume)
rhino-relay campaigns cancel <id>Cancel a campaign (POST /campaigns/{id}/cancel)
rhino-relay campaigns report <id>Get a campaign report (GET /campaigns/{id}/report)
rhino-relay campaigns recipients <id>List a campaign's send records (GET /campaigns/{id}/recipients)
rhino-relay imports create-csvStart a CSV import (POST /imports/csv)
rhino-relay imports create-mailchimpStart a Mailchimp import (POST /imports/mailchimp)
rhino-relay imports listList imports (GET /imports)
rhino-relay imports get <id>Get an import and its dry-run summary (GET /imports/{id})
rhino-relay imports delete <id>Cancel an uncommitted import (DELETE /imports/{id})
rhino-relay imports commit <id>Commit a dry-run import (POST /imports/{id}/commit)
rhino-relay exports listList exports (GET /exports)
rhino-relay exports createStart an export (POST /exports)
rhino-relay exports get <id>Get an export and its download link (GET /exports/{id})
rhino-relay health getCheck setup and sending health (GET /health)
rhino-relay setup verifyConnect the installed template (POST /setup/verify)
rhino-relay domains getGet domain and certificate status (GET /setup/domains)
rhino-relay domains setSet the tracking domain and an optional custom API domain (POST /setup/domains)
rhino-relay settings getGet settings (GET /settings)
rhino-relay settings updateUpdate settings (PATCH /settings)
rhino-relay keys listList API keys (GET /keys)
rhino-relay keys createCreate an API key (POST /keys)
rhino-relay keys revoke <id>Revoke an API key (DELETE /keys/{id})