> ## Documentation Index
> Fetch the complete documentation index at: https://plainrouter.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# CLI command reference

> Reference for Plainrouter CLI authentication, event, destination, delivery, report, and deletion commands.

Plainrouter CLI exposes nine API commands through the PyPI [`plainrouter`](https://pypi.org/project/plainrouter/) package `0.5.2`, npm [`@plainrouter/cli`](https://www.npmjs.com/package/@plainrouter/cli) package `0.5.1`, and the [official Homebrew tap](https://github.com/plainrouter/homebrew-tap). All distributions target signed API contract `0.5.0`. The contract also includes ingestion verification, which is available through the SDKs, direct REST, or MCP rather than a CLI command.

## Global options

| Option      | Purpose                                   |
| ----------- | ----------------------------------------- |
| `--json`    | Print the API response as formatted JSON. |
| `--help`    | Show help for the current command.        |
| `--version` | Print the CLI version.                    |

You can place `--json` on any API command. Authentication commands also support it.

## Authentication

| Command                   | Purpose                                                                                         |
| ------------------------- | ----------------------------------------------------------------------------------------------- |
| `plainrouter auth login`  | Prompt for and store the Signals workspace secret. The `0.5.x` prompt calls it a tracker token. |
| `plainrouter auth status` | Show the masked credential source and API base URL.                                             |
| `plainrouter auth logout` | Remove the stored local configuration.                                                          |

The CLI resolves configuration in this order:

1. `PLAINROUTER_TOKEN` for authentication.
2. `PLAINROUTER_BASE_URL` for the API origin.
3. The token and `baseUrl` in the local configuration file.
4. The production base URL, `https://plainrouter.com/api/v1`.

## Events

This request can send a real conversion. Use it only for an actual paid order with recorded full advertising consent and a [connected Meta destination](/docs/signals/connect-meta). Replace the order ID and decimal amount; the example omits `event_time` for an immediate event. Queued events must preserve their original payment timestamp.

```bash theme={null}
plainrouter events create --data '{
  "event_name": "Purchase",
  "event_id": "order-123",
  "consent_basis": "consent",
  "consent": {
    "ad_storage": "granted",
    "ad_user_data": "granted",
    "ad_personalization": "granted"
  },
  "value_data": {
    "value": "49.90",
    "currency": "EUR",
    "order_id": "order-123"
  }
}'
plainrouter events get order-123
plainrouter events list --per-page 25
```

| Command           | Options                                  |
| ----------------- | ---------------------------------------- |
| `events create`   | Required `--data <json>` request object. |
| `events get <id>` | Event ID as the positional argument.     |
| `events list`     | Optional `--per-page <count>`.           |

Use a stable event ID when creating an event so retries remain idempotent. A `duplicate: true` receipt means the original event exists, not that Meta accepted it. Inspect `events get` before considering a delivery replay. Use the [sandbox](/docs/api/sandbox) for synthetic validation without production writes.

## Destination test operations

Use a controlled destination and its current Meta Test Events code. Test mode changes delivery behavior for that destination: coordinate the test window, send the test purchase while mode is enabled, inspect Meta Test Events, and restore normal mode afterward even if the test fails. See [destination testing](/docs/signals/connect-meta#test-without-sending-a-real-purchase).

```bash theme={null}
plainrouter destinations test-mode DESTINATION_ID \
  --on --test-event-code TEST42
plainrouter destinations test-purchase DESTINATION_ID \
  --value 25.00 --currency EUR --order-id test-order-123
plainrouter destinations test-mode DESTINATION_ID --off
```

`destinations test-mode` requires exactly one of `--on` or `--off`. The test purchase accepts optional `--value`, `--currency`, and `--order-id` values.

## Replay deliveries

```bash theme={null}
plainrouter deliveries replay \
  --delivery-id 7 \
  --delivery-id 9 \
  --event-name Purchase \
  --limit 50
```

Repeat `--delivery-id` to select multiple deliveries. You can also filter by event name and cap the number of deliveries evaluated.

## Reports

```bash theme={null}
plainrouter reports reconciliation --date 2026-08-18
plainrouter reports emq
```

The reconciliation date must use `YYYY-MM-DD` format.

## Delete user data

```bash theme={null}
plainrouter user-data delete \
  --type email \
  --hash HASHED_IDENTIFIER
```

The identifier type is `email`, `phone`, or `external_id`. The command asks for confirmation before sending the deletion request.

The `0.5.x` CLI exposes the legacy SHA-256 form through `--hash`. Use direct REST or an SDK when you need to submit a verified raw identifier; both forms remain body-only and workspace-scoped.

Use `--yes` only in an automation that has already applied an equivalent confirmation gate:

```bash theme={null}
plainrouter user-data delete \
  --type email \
  --hash HASHED_IDENTIFIER \
  --yes \
  --json
```

## Handle errors

The CLI writes errors to standard error and exits with status `1`. Validation errors include field-level details when the API returns them.

A `401` response means the Signals workspace secret is missing, invalid, or no longer active. Stop retrying and replace the credential.
