# CLI

> Drive SendPing from the terminal — the official `sendping-cli`, or plain curl.

SendPing ships an official command-line tool: `npm install -g sendping-cli` (Node.js 18+) gives you a `sendping` command covering sends, domains, contacts, campaigns, and more — every API reference page includes its CLI invocation in the snippet tabs. To install it and send your first email, start with the [CLI Quickstart](https://www.sendping.co/docs/resources/cli-quickstart); the **Command surface** table below lists every group and subcommand.

Prefer zero install? Because the API is a plain JSON REST API, the terminal you already have — `curl` plus `jq` — covers the full surface too, and it works the same in scripts, CI/CD pipelines, and one-off debugging sessions. The rest of this page is the curl cookbook.

## Authentication

Keep your API key out of your shell history by exporting it once, then reference it in every request. The key is the same `mb_`-prefixed key you use everywhere else.

```bash
export SENDPING_API_KEY=mb_xxxxxxxxx

# Reuse it in any request
curl 'https://www.sendping.co/api/domains' \
  -H "Authorization: Bearer $SENDPING_API_KEY"
```

> **Warning:** Never paste a live key directly into a command you'll commit or share. Use an environment variable (or your CI secret store) so the key never lands in shell history or version control.

## Send an email

The terminal equivalent of [POST /emails](https://www.sendping.co/docs/api/emails-send) — provide the body inline, or read it from a file.

```bash
curl -X POST 'https://www.sendping.co/api/emails' \
  -H "Authorization: Bearer $SENDPING_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
    "from": "Acme <hello@yourdomain.com>",
    "to": ["delivered@test.sendping.co"],
    "subject": "Hello World",
    "text": "It works!"
  }'
```

Send an HTML body straight from a file with `@`-syntax — handy for templates you maintain on disk:

```bash
# Build the JSON with the file's HTML inlined, then send it
jq -n --rawfile html ./welcome.html '{
    from: "Acme <hello@yourdomain.com>",
    to: ["delivered@test.sendping.co"],
    subject: "Hello World",
    html: $html
  }' | curl -X POST 'https://www.sendping.co/api/emails' \
  -H "Authorization: Bearer $SENDPING_API_KEY" \
  -H 'Content-Type: application/json' \
  -d @-
```

## Pipe JSON through jq

Every endpoint returns JSON, so `jq` lets you extract exactly the field you need — the email `id`, a list of domains, an event log.

```bash
# Capture just the new email id
curl -s -X POST 'https://www.sendping.co/api/emails' \
  -H "Authorization: Bearer $SENDPING_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{ "from": "Acme <hello@yourdomain.com>", "to": ["delivered@test.sendping.co"], "subject": "Hi", "text": "Hello" }' \
  | jq -r '.id'

# List sendable domains by name — a domain can send while its status is any
# of verified, partially_verified or partially_failed
curl -s 'https://www.sendping.co/api/domains' \
  -H "Authorization: Bearer $SENDPING_API_KEY" \
  | jq -r '.data[] | select(.status | test("^(verified|partially_verified|partially_failed)$")) | .name'
```

## Send a batch from a file

Keep an array of email objects in a JSON file and POST it to [POST /emails/batch](https://www.sendping.co/docs/api/emails-batch). Use `@filename` to send the file as the request body.

```bash
curl -X POST 'https://www.sendping.co/api/emails/batch' \
  -H "Authorization: Bearer $SENDPING_API_KEY" \
  -H 'Content-Type: application/json' \
  -d @emails.json \
  | jq '.data'
```

## Use in CI/CD

Store your key as a CI secret and read it from the environment — no interactive login step is needed. For example, sending a deploy notification from GitHub Actions:

```yaml
# GitHub Actions
env:
  SENDPING_API_KEY: ${{ secrets.SENDPING_API_KEY }}
steps:
  - run: |
      curl -X POST 'https://www.sendping.co/api/emails' \
        -H "Authorization: Bearer $SENDPING_API_KEY" \
        -H 'Content-Type: application/json' \
        -d '{
          "from": "Acme <hello@yourdomain.com>",
          "to": ["delivered@test.sendping.co"],
          "subject": "Deploy complete",
          "text": "Version ${{ github.sha }} deployed."
        }'
```

## Handle errors in scripts

SendPing returns a structured error envelope with a `name` and `message`, and a non-2xx HTTP status. Capture the status code so a failed send fails your script:

```bash
status=$(curl -s -o /tmp/out.json -w '%{http_code}' -X POST 'https://www.sendping.co/api/emails' \
  -H "Authorization: Bearer $SENDPING_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{ "from": "Acme <hello@yourdomain.com>", "to": ["delivered@test.sendping.co"], "subject": "Hi" }')

if [ "$status" -ge 400 ]; then
  echo "Send failed:" >&2
  jq -r '.message' /tmp/out.json >&2
  exit 1
fi
```

> **Note:** See the [error reference](https://www.sendping.co/docs/api/errors) for the full envelope and every error name SendPing can return.

## Command surface

The official CLI mirrors the API one command group per resource — `sendping <resource> <action>`. The table below lists every group, its subcommands, and the docs for what it drives. Run `sendping <resource> --help` for the flags of any one of them, and see the [CLI Quickstart](https://www.sendping.co/docs/resources/cli-quickstart) to install it and send your first email.

| Command group | Subcommands | Docs |
| --- | --- | --- |
| `sendping emails` | `send`, `batch`, `get`, `list`, `update`, `cancel`, `sources`, `attachments`, `attachment` | [`/emails`](https://www.sendping.co/docs/api/emails-send), [`/emails/batch`](https://www.sendping.co/docs/api/emails-batch) |
| `sendping emails receiving` | `list`, `addresses`, `get`, `attachments`, `attachment`, `raw`, `forward`, `reply`, `delete` | [Receiving](https://www.sendping.co/docs/receiving/introduction) |
| `sendping domains` | `add`, `get`, `list`, `verify`, `update`, `mx-check`, `records-csv`, `delete`, plus `dns` (`detect`, `cloudflare`, `godaddy`, `namecheap`) and `claim` (`start`, `get`, `verify`) | [Domains](https://www.sendping.co/docs/domains/managing) |
| `sendping contacts` | `create`, `list`, `get`, `update`, `delete`, `add-to-segment`, `remove-from-segment`, `segments`, `topics`, `set-topics`, `batch`, `import`, `import-upload` | [Contacts](https://www.sendping.co/docs/audiences/contacts) |
| `sendping contact-properties` | `create`, `list`, `get`, `update`, `delete` | [Contact properties](https://www.sendping.co/docs/audiences/properties) |
| `sendping audiences` | `create`, `list`, `get`, `update`, `delete`, `import-sheet` | [Audiences](https://www.sendping.co/docs/audiences/overview) |
| `sendping segments` | `create`, `list`, `get`, `contacts`, `update`, `delete` | [Segments](https://www.sendping.co/docs/segments/overview) |
| `sendping topics` | `create`, `list`, `get`, `update`, `delete` | [Topics](https://www.sendping.co/docs/topics/overview) |
| `sendping campaigns` | `create`, `send`, `get`, `list`, `update`, `cancel`, `stats`, `engagement`, `ab`, `delete` | [Campaigns](https://www.sendping.co/docs/campaigns/managing) |
| `sendping templates` | `create`, `get`, `list`, `update`, `duplicate`, `publish`, `delete` | [Templates](https://www.sendping.co/docs/templates/overview) |
| `sendping automations` | `create`, `get`, `list`, `update`, `add-step`, `update-step`, `delete-step`, `runs`, `run`, `stop`, `ai`, `delete` | [Automations](https://www.sendping.co/docs/automations/overview) |
| `sendping webhooks` | `create`, `get`, `list`, `update`, `rotate`, `test`, `delete`, `verify` | [Webhooks](https://www.sendping.co/docs/webhooks/overview) |
| `sendping events` | `send`, `create`, `list`, `update`, `delete` | [Custom events](https://www.sendping.co/docs/automations/custom-events) |
| `sendping logs` | `list`, `get` | [Logs](https://www.sendping.co/docs/logs/overview) |
| `sendping polls` | `list`, `get` | [`/polls`](https://www.sendping.co/docs/api/polls-list) |
| `sendping api-keys` | `list` only — creating, re-scoping and revoking keys are **dashboard-only** and answer `403 dashboard_only` to any API-key caller | [API keys](https://www.sendping.co/docs/api-keys/overview) |

> **Note:** Authentication is the same for every command that reaches the API: a `mb_`-prefixed key, supplied via `SENDPING_API_KEY`, `--api-key`, or a CI secret. `webhooks verify` is the exception — it verifies a signature locally, sends nothing, needs no key, and does not accept `--api-key`. Output is JSON, so `jq` works the same across every command and every endpoint. For the full HTTP surface, see the [API reference](https://www.sendping.co/docs/api/emails-send).
