npm package: @saleshandy/saleshandy-cli
Description: Official CLI for SalesHandy Open API
Author: SalesHandy
Latest version: 0.1.8

# @saleshandy/saleshandy-cli

Official CLI for the [SalesHandy](https://www.saleshandy.com) Open API. Manage prospects, sequences, email accounts, tasks, and more from your terminal.

[![npm](https://img.shields.io/npm/v/@saleshandy/saleshandy-cli)](https://www.npmjs.com/package/@saleshandy/saleshandy-cli)

## Install

```sh
npm install -g @saleshandy/saleshandy-cli
```

Requires Node.js 18 or later.

## Quick Start

### 1. Get your API key

Go to [SalesHandy API Keys Settings](https://my.saleshandy.com/settings/api-keys) and generate an API key.

### 2. Authenticate

```sh
saleshandy auth login
# Prompts for your API key interactively

# Or pass it directly:
saleshandy auth login --api-key YOUR_API_KEY
```

### 3. Run commands

```sh
saleshandy prospects list
saleshandy sequences list --json
saleshandy tasks list --limit 5
```

## Authentication

### Login and profiles

The CLI stores your API key locally at `~/.config/saleshandy/config.json`.

```sh
# Default profile
saleshandy auth login --api-key YOUR_API_KEY

# Named profile (for multiple accounts)
saleshandy auth login --api-key ANOTHER_KEY --profile client-a

# Use a specific profile for a command
saleshandy prospects list --profile client-a

# Switch default profile
saleshandy auth switch client-a

# See all profiles
saleshandy auth status

# Remove a profile
saleshandy auth logout
saleshandy auth logout --profile client-a
```

### Environment variable

You can skip login entirely by setting the env var. This is useful for CI/CD:

```sh
export SALESHANDY_API_KEY=your_key
saleshandy prospects list
```

### Per-command override

```sh
saleshandy prospects list --api-key YOUR_KEY
```

**Precedence:** `--api-key` flag > `SALESHANDY_API_KEY` env var > saved profile.

## Output Formats

Every command supports three output formats:

```sh
# Table (default) — human-readable
saleshandy prospects list

# JSON — for scripts and piping
saleshandy prospects list --json

# CSV — for spreadsheets
saleshandy prospects list --csv
```

Pipe JSON output to `jq` for filtering:

```sh
saleshandy prospects list --json | jq '.[].email'
```

Export to a CSV file:

```sh
saleshandy prospects list --csv > contacts.csv
```

Disable colored output:

```sh
saleshandy prospects list --no-color
```

## Getting Help

```sh
# List all topics
saleshandy --help

# List commands in a topic
saleshandy prospects --help

# See flags, args, and examples for a specific command
saleshandy prospects list --help
saleshandy analytics sequence-stats --help
```

Every command has `--help`. **When in doubt, add `--help` to see exactly what flags and arguments are required.**

## Common Patterns

### Pagination

All list commands support `--limit` and `--page`:

```sh
saleshandy prospects list --limit 50 --page 1
saleshandy prospects list --limit 50 --page 2
```

### Sorting

List commands support `--sort` (asc/desc) and `--sort-by`:

```sh
saleshandy prospects list --sort desc --sort-by createdAt
saleshandy tasks list --sort-order ASC --sort-by priority
```

**Note:** Valid `--sort-by` values differ per resource. Run `<command> --help` to see available options.

### Passing IDs

Many commands require IDs (sequence IDs, prospect IDs, etc.). IDs in SalesHandy are hashed strings like `gOwE5l64wb`. You get these from list commands:

```sh
# Step 1: List sequences to find the ID
saleshandy sequences list
# Output shows ID column: gOwE5l64wb

# Step 2: Use that ID in another command
saleshandy analytics sequence-stats --sequence-id gOwE5l64wb
```

### Comma-separated IDs

Some commands accept multiple IDs. Pass them comma-separated:

```sh
saleshandy sequences status-update --sequence-ids gOwE5l64wb,aB3xK9mP2w --status pause
saleshandy tasks bulk-skip --task-ids id1,id2,id3
```

### JSON body via --file

Import and connect commands accept a JSON file:

```sh
saleshandy prospects import --file prospects.json
saleshandy email-accounts connect --file accounts.json
saleshandy enrichment contact --file leads.json
```

### Async operations (import, enrichment, connect)

Some operations are async. They return a request ID you can poll:

```sh
# Start an import
saleshandy prospects import --file data.json
# Output: ✓ Prospect import has started. Request ID: req_abc123

# Check status
saleshandy prospects import-status req_abc123

# For enrichment, use --wait to poll automatically:
saleshandy enrichment status req_abc123 --wait
```

## Command Reference

### auth — Authentication

```sh
saleshandy auth login                          # Interactive login
saleshandy auth login --api-key KEY            # Non-interactive
saleshandy auth login --api-key KEY --profile staging
saleshandy auth logout                         # Remove current profile
saleshandy auth logout --profile staging       # Remove named profile
saleshandy auth status                         # Show all profiles
saleshandy auth switch staging                 # Switch active profile
```

### prospects — Manage Prospects

```sh
saleshandy prospects list                                    # List all prospects
saleshandy prospects list --search "john@acme.com"           # Search by email/name
saleshandy prospects list --limit 50 --page 2                # Paginate
saleshandy prospects list --include-custom-fields             # Include custom fields
saleshandy prospects import --file prospects.json            # Import from file
saleshandy prospects import-status REQUEST_ID                # Check import status
saleshandy prospects verification-status --emails "a@b.com,c@d.com"
saleshandy prospects attribute --attribute-id ID --prospect-id ID

# Update prospect status in a sequence
saleshandy prospects status update \
  --prospect-id ID --sequence-id ID --step-id ID --status paused
# Status options: replied, finished, paused, unsubscribed, active

# Tags
saleshandy prospects tags list
saleshandy prospects tags list --search "VIP"
saleshandy prospects tags assign --prospects '[{"prospectId":"ID","tagId":"ID"}]'
saleshandy prospects tags unassign --data '[{"prospects":["ID"]}]'
```

### sequences — Manage Sequences

```sh
saleshandy sequences list                                        # List all
saleshandy sequences list --search "Growth" --limit 10           # Filter
saleshandy sequences status-update --sequence-ids ID1,ID2 --status pause

# Email accounts on a sequence
saleshandy sequences email-accounts list --sequence-id ID
saleshandy sequences email-accounts add --sequence-id ID --email-account-ids ID1,ID2
saleshandy sequences email-accounts remove --sequence-id ID --email-account-ids ID1

# Import prospects into a sequence
saleshandy sequences prospects-import --file data.json

# Add existing contacts to a sequence step
saleshandy sequences contacts-add --sequence-id ID --step-id ID --contact-ids ID1,ID2

# Get step details
saleshandy sequences steps get --sequence-id ID --step-id ID
```

### email-accounts — Email Accounts

```sh
saleshandy email-accounts list                                    # List all
saleshandy email-accounts list --search "gmail"                   # Filter
saleshandy email-accounts connect --file accounts.json            # Connect via SMTP/IMAP
saleshandy email-accounts connect-status REQUEST_ID               # Check connection
saleshandy email-accounts reconnect --email-account-ids ID1,ID2
saleshandy email-accounts bulk-update --email-account-ids ID1,ID2 --is-paused
```

### enrichment — Lead Finder

```sh
# Enrich contacts
saleshandy enrichment contact --linkedin-urls "https://linkedin.com/in/person"
saleshandy enrichment contact --file contacts.json --reveal-phone
saleshandy enrichment contact --file contacts.json --webhook-url https://example.com/hook

# Enrich companies
saleshandy enrichment company --domains "acme.com,startup.io"
saleshandy enrichment company --file companies.json

# Check status and get results
saleshandy enrichment status REQUEST_ID
saleshandy enrichment status REQUEST_ID --wait    # Polls until complete
saleshandy enrichment result REQUEST_ID

# Check credits and rate limits
saleshandy enrichment credits
saleshandy enrichment rate-limits
```

### unified-inbox — Emails

```sh
saleshandy unified-inbox unread-count
saleshandy unified-inbox outcomes --limit 10
saleshandy unified-inbox emails list --limit 20 --search "acme"
saleshandy unified-inbox emails list --sentiment positive --start-date 2025-01-01
saleshandy unified-inbox emails thread THREAD_ID
saleshandy unified-inbox emails get THREAD_ID EMAIL_ID

# Reply to an email
saleshandy unified-inbox emails reply \
  --thread-id ID --email-id ID \
  --to "john@acme.com" --content "Thanks for reaching out!"
```

### analytics — Reports

```sh
# Sequence stats (pass sequence ID from `sequences list`)
saleshandy analytics sequence-stats --sequence-id gOwE5l64wb

# Consolidated stats across multiple sequences
saleshandy analytics consolidated-stats \
  --sequence-ids ID1,ID2 --start-date 2025-01-01 --end-date 2025-12-31

# Email account stats
saleshandy analytics email-account-stats --email-id ID

# Team stats
saleshandy analytics team-stats \
  --user-ids ID1,ID2 \
  --start-date 2025-01-01T00:00:00.000+00:00 \
  --end-date 2025-12-31T23:59:59.000+00:00 \
  --count-by absolute --type prospect \
  --order-by total --limit 10 --page 1
```

### tasks — Task Management

```sh
saleshandy tasks list                                    # List all tasks
saleshandy tasks list --status overdue --limit 10        # Filter by status
saleshandy tasks list --sequence-id ID                   # Filter by sequence
saleshandy tasks get TASK_ID                             # Task details
saleshandy tasks counts                                  # Counts by status
saleshandy tasks assignees                               # List assignees

# Actions
saleshandy tasks complete TASK_ID
saleshandy tasks skip TASK_ID
saleshandy tasks snooze TASK_ID --snooze-until "2025-12-25T09:00:00.000Z"
saleshandy tasks note-update TASK_ID --note "Called, no answer"

# Bulk actions
saleshandy tasks bulk-skip --task-ids ID1,ID2,ID3
saleshandy tasks bulk-snooze --task-ids ID1,ID2 --snooze-until "2025-12-25T09:00:00.000Z"
saleshandy tasks bulk-status BULK_ACTION_ID
```

### dnc — Do Not Contact

```sh
saleshandy dnc list                                      # List DNC lists
saleshandy dnc items DNC_LIST_ID                         # Items in a list
saleshandy dnc add --dnc-list-id ID --items "spam@bad.com,baddomain.com"
saleshandy dnc search --search "bad.com" --type domain
```

### fields — Custom Fields

```sh
saleshandy fields list --system-fields     # Include system fields
saleshandy fields list --no-system-fields  # Custom fields only
```

### clients — Client Management

```sh
saleshandy clients list
saleshandy clients list --search "Acme"
saleshandy clients assign --resource-type sequence --client-id ID --resource-ids ID1,ID2
saleshandy clients assign --resource-type emailAccount --client-id ID --resource-ids ID1
```

### user — Team Info

```sh
saleshandy user team-members
saleshandy user team-members --json
```

### warmup — Email Warmup

```sh
saleshandy warmup report EMAIL_ACCOUNT_ID 2025-03-15
```

## Global Flags

These flags work on every command:

| Flag | Description |
|------|-------------|
| `--json` | Output as JSON |
| `--csv` | Output as CSV |
| `--profile <name>` | Use a named auth profile |
| `--api-key <key>` | Override API key for this command |
| `--no-color` | Disable colored output |
| `--help` | Show help |

## Shell Autocomplete

Set up tab completion:

```sh
saleshandy autocomplete
```

Follow the printed instructions for your shell (bash/zsh/fish).

## FAQ

**Q: How do I find the ID I need to pass to a command?**
A: Run the list command for that resource first. For example, `saleshandy sequences list` shows sequence IDs, then use that ID with `saleshandy analytics sequence-stats --sequence-id <ID>`.

**Q: A command says a flag is required but I don't know the value.**
A: Run `<command> --help` to see the description and valid options for each flag. For IDs, list the parent resource first.

**Q: How do I pass JSON data?**
A: Use `--file path/to/file.json` for import/connect/enrichment commands. For tag operations, pass inline JSON as a string: `--prospects '[{"prospectId":"ID","tagId":"ID"}]'`

**Q: Can I use this in CI/CD?**
A: Yes. Set `SALESHANDY_API_KEY` as an environment variable and use `--json` for machine-readable output. Example: `SALESHANDY_API_KEY=xxx saleshandy prospects list --json`

**Q: How do I check the status of an async operation?**
A: Import, enrichment, and connect operations return a request ID. Use the corresponding `*-status` command: `saleshandy prospects import-status <requestId>` or `saleshandy enrichment status <requestId> --wait`

## Links

- [SalesHandy](https://www.saleshandy.com)
- [API Documentation](https://open-api.saleshandy.com/api-doc/)
- [Issues & Feedback](https://github.com/saleshandy/saleshandy-cli/issues)

## License

MIT - see [LICENSE](LICENSE)