CLI Quickstart
Install the official sendping CLI and send your first email from the terminal in three commands.
SendPing ships an official command-line tool. sendping-cli (5.1.1 on npm) installs a `sendping` command that covers the whole API — sends, domains, contacts, segments, topics, campaigns, templates, automations, webhooks, events, logs and polls. It wraps the official `sendping` Node.js SDK, so a CLI call and an SDK call hit exactly the same endpoints.
Every command prints the API response as JSON on stdout, which makes the CLI both the quickest way to try an endpoint by hand and a safe building block in scripts and CI.
Prerequisites
- Node.js 18 or newer —
sendping-clideclaresengines.node: ">=18". - A SendPing API key — the
mb_-prefixed secret you create in the dashboard. - A verified domain to send from.
1. Install the CLI
npm install -g sendping-cli
# the package is sendping-cli; the command it installs is sendping
sendping --version
# 5.1.1Rather not install anything? Run it straight from npm — name both the package and the binary, because they differ:
npx --package sendping-cli@5.1.1 sendping --version--help works at every level: sendping --help lists the resource groups, sendping emails --help lists that group's subcommands, and sendping emails send --help lists every flag.
2. Authenticate
There is no login step. Every invocation that talks to the API resolves your key from the SENDPING_API_KEY environment variable, or from --api-key on that command; with neither, the CLI exits 1 with a cli_error. The one exception is sendping webhooks verify, which checks a signature locally, makes no request, and therefore takes no key — passing --api-key to it fails with an unknown-option error. Export your key once so it stays out of your shell history, then prove it works:
export SENDPING_API_KEY=mb_xxxxxxxxx
# any command exercises the key — this one lists your sending domains
sendping domains listPass --base-url (or set SENDPING_BASE_URL) to point the CLI at a different API host.
sendping api-keys list is the CLI's entire key surface), so a leaked key cannot mint, widen, or revoke another. See API keys.3. Send your first email
Send from your verified domain to delivered@test.sendping.co, the mailbox simulator: it is intercepted before the provider is contacted and synthesizes a delivery, so nothing reaches a real inbox. --to, --cc, --bcc and --reply-to are repeatable and also accept comma-separated values.
sendping emails send \
--from 'Acme <hello@yourdomain.com>' \
--to delivered@test.sendping.co \
--subject 'Hello from the CLI' \
--html '<p>Your first email 🎉</p>'A successful send prints the new email id — the same body POST /emails returns:
{
"id": "49a3999c-0ce1-4ea6-ab68-afcd6dc2e794"
}example.com, example.net, example.org and anything under .test, .invalid, .localhost or .example are blocked outright and answer 422. Simulator sends still debit your quota per recipient, exactly like a real send.4. See what happened
Read the email back by id for its current status and ordered event log, or list your recent sends:
sendping emails get 49a3999c-0ce1-4ea6-ab68-afcd6dc2e794
sendping emails list --limit 5
sendping emails list --status delivered --search invoice
sendping emails list --folder sent --limit 5{
"object": "email",
"id": "49a3999c-0ce1-4ea6-ab68-afcd6dc2e794",
"from": "Acme <hello@yourdomain.com>",
"to": ["delivered@test.sendping.co"],
"subject": "Hello from the CLI",
"status": "delivered",
"last_event": "delivered",
"events": [
{ "type": "sent", "created_at": "2026-06-23T10:00:00.000Z" },
{ "type": "delivered", "created_at": "2026-06-23T10:00:04.512Z" }
]
}Output and exit codes
Responses are pretty-printed JSON by default; --json switches to compact JSON for piping into jq. stdout stays JSON-only either way — a failure prints its error object to stderr and exits 1, so sendping … | jq never has to strip a diagnostic.
id=$(sendping emails send --json \
--from 'Acme <hello@yourdomain.com>' \
--to delivered@test.sendping.co \
--subject 'Hello from the CLI' \
--text 'It works!' | jq -r '.id') || exit 1The error object is always { statusCode, name, message }. Branch on name, never on message:
| Where it came from | `statusCode` | `name` |
|---|---|---|
| The API rejected the request | the HTTP status | the API's reason, e.g. validation_error, daily_quota_exceeded |
| The request never reached the API | 0 | network_error |
| The CLI rejected your flags before sending | null | cli_error |
Beyond the first send
A few flags on emails send worth knowing early:
--textalongside (or instead of)--html, plus--preview-textfor the inbox preheader.--template-idor--template-aliaswith--variables '{"first_name":"Ada"}'to send a stored template.--attachment ./invoice.pdf(read and base64-encoded locally) or--attachment-url(fetched server-side) — both repeatable, capped at 25 MB per file and 40 MB per message. See Attachments.--idempotency-key order-12345onemails sendandemails batchso a retry cannot send twice. See Idempotency keys.sendping emails batch --file ./batch.jsonto send up to 100 emails in one request. See Batch sending.
Scheduling uses --scheduled-at — an ISO 8601 timestamp or a phrase like in 1 min, up to 30 days ahead. A scheduled message skips the mailbox simulator, so schedule to a real address you control instead:
sendping emails send \
--from 'Acme <hello@yourdomain.com>' \
--to you@yourdomain.com \
--subject 'Your weekly digest' \
--html '<p>Here is what you missed.</p>' \
--scheduled-at 2026-09-01T09:00:00Z
# reschedule or cancel while it is still pending
sendping emails update 49a3999c-0ce1-4ea6-ab68-afcd6dc2e794 --scheduled-at 'in 2 hours'
sendping emails cancel 49a3999c-0ce1-4ea6-ab68-afcd6dc2e794delivered@test.sendping.co with --scheduled-at: the simulator only fires on an immediate send, so a scheduled message to it is treated as suppressed and rejected with 422. See Schedule emails.Next steps
- The full command surface, plus the equivalent
curlcookbook: CLI. - Non-interactive patterns for agents and CI — stdin piping, batches, safe retries, webhook feedback loops: CLI for AI agents.
- A typed client instead of a shell: the official SDKs for Node.js, Python, Go, Ruby, PHP, Rust, Java and .NET.
- Every endpoint and field: the API reference.