npm package: @postcardaidev/cli
Description: PostcardAI CLI - Send postcards from the command line
Author: PostcardAI
Latest version: 0.1.1

# @postcardaidev/cli

Command-line interface for PostcardAI - manage your postcards from the terminal.

## Installation

### Using npx (Recommended)

No installation needed - just run commands with npx:

```bash
npx @postcardaidev/cli login
npx @postcardaidev/cli whoami
```

### Global Installation

For faster startup, install globally:

```bash
npm install -g @postcardaidev/cli
```

Then use without npx:

```bash
postcardai login
postcardai whoami
```

---

## Quick Start

```bash
# 1. Authenticate
postcardai login

# 2. Check your balance
postcardai balance

# 3. Send a postcard
postcardai send \
  --to "John Doe, 123 Main St, New York, NY 10001" \
  --prompt "A beautiful sunset over the city"
```

---

## Authentication Commands

### login

Authenticate with your PostcardAI account:

```bash
postcardai login [options]
```

**Options:**
- `--no-browser` - Don't automatically open the browser

**What happens:**
1. The CLI generates a device code
2. Your browser opens to `https://postcard.ai/device/authorize`
3. You approve the authorization and select your organization
4. The CLI receives an API key and stores it locally

**Example:**

```bash
$ postcardai login

To complete authentication:

  1. Visit: https://postcard.ai/device/authorize
  2. Enter code: ABCD-1234

Opening browser...
Waiting for authorization...

Successfully authenticated!

  Organization: Acme Inc
  Environment:  live
```

### logout

Remove stored credentials:

```bash
postcardai logout
```

### whoami

Check your current authentication status:

```bash
postcardai whoami [options]
```

**Options:**
- `--verify` - Verify credentials are still valid with the API

### config

View and modify configuration:

```bash
# Show all config
postcardai config get

# Get specific value
postcardai config get environment

# Set value
postcardai config set environment test

# Show config file path
postcardai config path
```

---

## Account & Credits

### account

Show your account details and usage:

```bash
postcardai account
```

### balance

Show your current credit balance:

```bash
postcardai balance
```

### transactions

Show credit transaction history:

```bash
postcardai transactions [options]
```

**Options:**
- `-l, --limit <number>` - Number of results (default: 20)
- `-o, --offset <number>` - Offset for pagination (default: 0)
- `--type <type>` - Filter by type: `purchase`, `usage`, `refund`, `adjustment`

### estimate

Estimate mailing cost before sending:

```bash
postcardai estimate [options]
```

**Options:**
- `-r, --recipients <number>` - Number of recipients (required)
- `--size <size>` - Postcard size: `4x6`, `6x9`, `6x11` (default: 4x6)
- `--steps <number>` - Number of steps in campaign (default: 1)

**Example:**

```bash
postcardai estimate -r 100 --size 6x9
```

---

## Quick Send

### send

Send a postcard with a single command:

```bash
postcardai send [options]
```

**Options:**
- `--to <address>` - Recipient address: "Name, Street, City, STATE ZIP" (required)
- `--prompt <text>` - Design prompt for the postcard (required)
- `--size <size>` - Postcard size: `4x6`, `5x7`, `6x9`, `6x11` (default: 4x6)
- `--name <name>` - Campaign name
- `--preview` - Preview before sending

**Example:**

```bash
postcardai send \
  --to "Jane Smith, 456 Oak Ave, Los Angeles, CA 90001" \
  --prompt "A modern real estate postcard with a luxury home" \
  --size 6x9 \
  --preview
```

---

## Contacts

### contacts list

List your contacts:

```bash
postcardai contacts list [options]
```

**Options:**
- `-l, --limit <number>` - Number of results (default: 20)
- `-o, --offset <number>` - Offset for pagination (default: 0)
- `-s, --search <query>` - Search contacts
- `--status <status>` - Filter by status: `active`, `inactive`, `bounced`, `do_not_mail`

### contacts get

Get contact details:

```bash
postcardai contacts get <id>
```

### contacts create

Create a new contact:

```bash
postcardai contacts create [options]
```

**Options:**
- `--street <street>` - Street address (required)
- `--city <city>` - City (required)
- `--state <state>` - State, 2-letter code (required)
- `--zip <zip>` - ZIP code (required)
- `--first-name <name>` - First name
- `--last-name <name>` - Last name
- `--full-name <name>` - Full name
- `--unit <unit>` - Unit/Apt number

### contacts delete

Delete a contact:

```bash
postcardai contacts delete <id>
```

### contacts history

Get contact mailing history:

```bash
postcardai contacts history <id>
```

### contacts match

Match a person by email, phone, or property address:

```bash
postcardai contacts match [options]
```

**Options (provide one):**
- `--email <email>` - Match by email
- `--phone <phone>` - Match by phone
- `--street <street>` + `--city <city>` + `--state <state>` + `--zip <zip>` - Match by property address

### contacts batch

Batch import contacts from a JSON file:

```bash
postcardai contacts batch <file> [options]
```

**Options:**
- `--no-skip-invalid` - Stop on first invalid contact instead of skipping

**JSON file format:**

```json
[
  {
    "firstName": "John",
    "lastName": "Doe",
    "street": "123 Main St",
    "city": "New York",
    "state": "NY",
    "zip": "10001"
  },
  {
    "fullName": "Jane Smith",
    "street": "456 Oak Ave",
    "unit": "Apt 2B",
    "city": "Los Angeles",
    "state": "CA",
    "zip": "90001"
  }
]
```

### contacts match-batch

Batch match contacts from a JSON file:

```bash
postcardai contacts match-batch <file> [options]
```

**Options:**
- `--create-missing` - Create contacts for unmatched records

**JSON file format:**

```json
[
  { "email": "john@example.com" },
  { "phone": "+15551234567" },
  {
    "propertyAddress": {
      "street": "123 Main St",
      "city": "New York",
      "state": "NY",
      "zip": "10001"
    }
  }
]
```

---

## Lists

### lists list

List your contact lists:

```bash
postcardai lists list [options]
```

**Options:**
- `-l, --limit <number>` - Number of results (default: 20)
- `-o, --offset <number>` - Offset for pagination (default: 0)

### lists get

Get list details:

```bash
postcardai lists get <id>
```

### lists create

Create a new list:

```bash
postcardai lists create [options]
```

**Options:**
- `--name <name>` - List name (required)
- `--description <text>` - List description

### lists delete

Delete a list:

```bash
postcardai lists delete <id>
```

### lists add-contacts

Add contacts to a list:

```bash
postcardai lists add-contacts <listId> <contactIds...>
```

**Example:**

```bash
postcardai lists add-contacts lst_abc123 con_123 con_456 con_789
```

---

## Designs

### designs list

List your designs:

```bash
postcardai designs list [options]
```

**Options:**
- `-l, --limit <number>` - Number of results (default: 20)
- `-o, --offset <number>` - Offset for pagination (default: 0)
- `-s, --search <query>` - Search designs
- `--status <status>` - Filter by status: `draft`, `generating`, `active`, `completed`, `archived`
- `--published` - Only show published designs

### designs get

Get design details:

```bash
postcardai designs get <id>
```

### designs create

Create a new AI-generated design:

```bash
postcardai designs create [options]
```

**Options:**
- `--prompt <text>` - Design prompt (required)
- `--name <name>` - Design name
- `--size <size>` - Postcard size: `4x6`, `5x7`, `6x9`, `6x11` (default: 4x6)
- `--orientation <orientation>` - `landscape` or `portrait` (default: landscape)

### designs iterate

Generate a new iteration of a design:

```bash
postcardai designs iterate <id> [options]
```

**Options:**
- `--prompt <text>` - Refinement prompt

### designs publish

Publish a design iteration:

```bash
postcardai designs publish <id> [options]
```

**Options:**
- `--iteration <number>` - Iteration number to publish (required)

---

## Mailings

### mailings list

List your mailings:

```bash
postcardai mailings list [options]
```

**Options:**
- `-l, --limit <number>` - Number of results (default: 20)
- `-o, --offset <number>` - Offset for pagination (default: 0)
- `--status <status>` - Filter by status: `previewing`, `processing`, `active`, `paused`, `completed`, `cancelled`

### mailings get

Get mailing details:

```bash
postcardai mailings get <id>
```

### mailings send

Send a mailing that's in preview mode:

```bash
postcardai mailings send <id>
```

### mailings cancel

Cancel a mailing:

```bash
postcardai mailings cancel <id>
```

### mailings previews

Get preview images for a mailing:

```bash
postcardai mailings previews <id>
```

### mailings recipients

List recipients and delivery status:

```bash
postcardai mailings recipients <id> [options]
```

**Options:**
- `-l, --limit <number>` - Number of results (default: 20)
- `-o, --offset <number>` - Offset for pagination (default: 0)
- `--status <status>` - Filter by status: `pending`, `sent`, `in_transit`, `delivered`, `returned`

### mailings analytics

Get mailing analytics:

```bash
postcardai mailings analytics <id>
```

---

## Brands

### brands list

List your brand profiles:

```bash
postcardai brands list
```

### brands get

Get brand details:

```bash
postcardai brands get <id>
```

### brands create

Create a new brand:

```bash
postcardai brands create [options]
```

**Options:**
- `--name <name>` - Brand name (required)
- `--goal-type <type>` - Goal type, e.g., `seller_leads` (required)
- `--goal-label <label>` - Goal label, e.g., "Get Seller Leads" (required)
- `--description <text>` - Brand description
- `--voice <text>` - Brand voice

### brands update

Update a brand:

```bash
postcardai brands update <id> [options]
```

**Options:**
- `--name <name>` - Brand name
- `--goal-type <type>` - Goal type
- `--goal-label <label>` - Goal label
- `--description <text>` - Brand description
- `--voice <text>` - Brand voice
- `--brand-rules <text>` - Brand rules
- `--goal-rules <text>` - Goal rules
- `--logo-url <url>` - Logo URL
- `--logo-description <text>` - Logo description
- `--logo-rules <text>` - Logo rules
- `--always-include-logo` / `--no-always-include-logo` - Always include logo
- `--headshot-url <url>` - Headshot URL
- `--headshot-description <text>` - Headshot description
- `--always-include-headshot` / `--no-always-include-headshot` - Always include headshot

### brands delete

Delete a brand:

```bash
postcardai brands delete <id>
```

### brands set-default

Set a brand as default:

```bash
postcardai brands set-default <id>
```

---

## Return Addresses

### addresses list

List your return addresses:

```bash
postcardai addresses list
```

### addresses get

Get return address details:

```bash
postcardai addresses get <id>
```

### addresses create

Create a return address:

```bash
postcardai addresses create [options]
```

**Options:**
- `--name <name>` - Name or company on address (required)
- `--address1 <address>` - Street address (required)
- `--city <city>` - City (required)
- `--state <state>` - State, 2-letter code (required)
- `--zip <zip>` - ZIP code (required)
- `--address2 <address>` - Address line 2
- `--label <label>` - Label for this address
- `--default` - Set as default address

### addresses update

Update a return address:

```bash
postcardai addresses update <id> [options]
```

**Options:**
- `--name <name>` - Name or company on address
- `--address1 <address>` - Street address
- `--address2 <address>` - Address line 2
- `--city <city>` - City
- `--state <state>` - State, 2-letter code
- `--zip <zip>` - ZIP code
- `--label <label>` - Label for this address

### addresses delete

Delete a return address:

```bash
postcardai addresses delete <id>
```

### addresses set-default

Set a return address as default:

```bash
postcardai addresses set-default <id>
```

---

## Webhooks

### webhooks list

List your webhooks:

```bash
postcardai webhooks list
```

### webhooks get

Get webhook details (includes secret):

```bash
postcardai webhooks get <id>
```

### webhooks create

Create a webhook:

```bash
postcardai webhooks create [options]
```

**Options:**
- `--url <url>` - Webhook endpoint URL (required)
- `--events <events...>` - Events to subscribe to (required)

**Example:**

```bash
postcardai webhooks create \
  --url https://example.com/webhook \
  --events mailing.sent mailing.delivered postcard.returned
```

### webhooks delete

Delete a webhook:

```bash
postcardai webhooks delete <id>
```

### webhooks rotate-secret

Rotate webhook signing secret:

```bash
postcardai webhooks rotate-secret <id>
```

### webhooks test

Send a test event to webhook:

```bash
postcardai webhooks test <id>
```

### webhooks enable

Enable a webhook:

```bash
postcardai webhooks enable <id>
```

### webhooks disable

Disable a webhook:

```bash
postcardai webhooks disable <id>
```

---

## Configuration

Credentials are stored in `~/.postcardai/config.json`:

```json
{
  "apiKey": "pcai_sk_live_xxxxxxxxxxxxxxxxxxxxxxxx",
  "keyId": "key_abc123def456",
  "organizationId": "123e4567-e89b-12d3-a456-426614174000",
  "organizationName": "Acme Inc",
  "organizationSlug": "acme-inc",
  "environment": "live"
}
```

### Security

- The config file is created with `0600` permissions (owner read/write only)
- Your API key is a long-lived credential - treat it like a password
- To revoke access, delete the API key from [Developer Settings](https://postcard.ai/settings/developer)

### Environment Variables

| Variable | Description |
|----------|-------------|
| `POSTCARDAI_API_URL` | Override API base URL (default: `https://api.postcard.ai/v1`) |
| `POSTCARDAI_CONFIG_PATH` | Custom config file location |

---

## Troubleshooting

### Browser doesn't open

Use the `--no-browser` flag and manually visit the URL:

```bash
postcardai login --no-browser
```

Then copy the URL and code shown in the terminal.

### Code expired

Device codes expire after 15 minutes. If yours expired, just run `login` again:

```bash
postcardai login
```

### Wrong organization

Log out and log in again, selecting a different organization:

```bash
postcardai logout
postcardai login
```

### Credentials invalid

Your API key may have been revoked. Verify with:

```bash
postcardai whoami --verify
```

If invalid, log in again to create a new key.

---

## MCP Server Integration

After authenticating with the CLI, the [PostcardAI MCP Server](../mcp-server) automatically uses your stored credentials. No additional configuration needed.

---

## License

MIT