---
title: "FirstSales CLI Quickstart | FirstSales"
description: "Install the FirstSales CLI, authenticate with an API key, and run your first safe commands — whoami, org/workspace discovery, dry-run, and idempotency."
canonical: "https://firstsales.io/tutorial/firstsales-cli-quickstart/"
---

[Home](/)/[Tutorials](/tutorial/)/FirstSales CLI Quickstart

Developer & CLI

# FirstSales CLI Quickstart

Install the FirstSales CLI, authenticate with an API key, and run your first safe commands — whoami, org/workspace discovery, dry-run, and idempotency.

8 min read·Advanced·7 steps

1. 1  
## Install the CLI  
The FirstSales CLI is an npm package. Install it globally to get the `firstsales` binary:  
```  
npm install -g @firstsales.io/cli  
firstsales --version  
```
2. 2  
## Authenticate  
Create a Developer API key in **Settings → API**, then give the CLI the key and base URL. The cleanest way is environment variables:  
```  
export FIRSTSALES_API_KEY="fs-key-..."  
export FIRSTSALES_BASE_URL="https://api.app.firstsales.io"  
```
3. 3  
## Verify with whoami and doctor  
Before doing anything, confirm the key resolves to the right context. `whoami` shows your user, org, and workspace; `doctor` checks your setup:  
```  
firstsales whoami --json  
firstsales doctor  
```
4. 4  
## Understand the global flags  
Every command shares the same flags — learn these once:  
   * `--org <id>` / `--workspace <id>` — target scope (most commands need both).  
   * `--json` (default) / `--pretty` — output format.  
   * `--data '<json>'` / `--data-file <path>` — request body.  
   * `--idempotency-key <key>` — safe retries on creates.  
   * `--dry-run` — preview the request without sending it.  
   * `--confirm` — required for any destructive (delete) command.  
   * `--api-key` / `--base-url` / `--profile` — override auth per call.
5. 5  
## Discover your org and workspace  
Most commands are scoped to an org and workspace. List them, then reuse the IDs:  
```  
firstsales organizations list  
firstsales workspaces list --org ORG_ID  
firstsales campaigns list --org ORG_ID --workspace WS_ID  
```
6. 6  
## Make a safe first mutation  
Follow the golden loop: **inspect first, mutate deliberately, verify after**. Preview with `--dry-run`, then create with an idempotency key, then re-read to confirm:  
```  
# Preview — no write happens  
firstsales contacts create --org ORG_ID --workspace WS_ID \  
  --data '{"email":"jane@acme.com","first_name":"Jane"}' --dry-run  
# Create for real, idempotently  
firstsales contacts create --org ORG_ID --workspace WS_ID \  
  --data '{"email":"jane@acme.com","first_name":"Jane"}' \  
  --idempotency-key jane-acme-2026-01  
# Verify  
firstsales contacts list --org ORG_ID --workspace WS_ID  
```
7. 7  
## Delete deliberately  
Destructive commands refuse to run without `--confirm` — this is intentional friction so an agent or a fat-fingered command can't wipe data by accident:  
```  
firstsales contacts delete --org ORG_ID --workspace WS_ID \  
  --contact CONTACT_ID --confirm  
```

## Pro tips

Hard-won shortcuts that keep warm-up on track.

1

### Inspect first, mutate deliberately, verify after

The CLI is built around this loop. List before you change, --dry-run the change, run it, then re-read to confirm. It's slower to type and far cheaper than undoing a bad write.

2

### \--json is for machines, --pretty is for you

Output defaults to compact JSON so scripts and agents can parse it. Add --pretty when a human is reading, but keep --json in pipelines.

3

### Never echo your key

Pass auth via FIRSTSALES\_API\_KEY or a profile, not inline where it lands in shell history or logs. The CLI never prints raw keys — don't undo that by echoing the env var.

4

### Idempotency keys are free insurance

Any create that might be retried should carry --idempotency-key. A replayed command becomes a no-op instead of a duplicate.

## Frequently asked questions

How do I install the CLI?

`npm install -g @firstsales.io/cli`, which gives you the `firstsales` binary. It maps directly to the public `/api/v1` Developer API.

How does authentication work?

Set `FIRSTSALES_API_KEY` (and optionally `FIRSTSALES_BASE_URL`) in your environment, or pass `--api-key` / `--base-url` per command. Verify with `firstsales whoami --json`.

Why do commands need --org and --workspace?

Resources are scoped to an organization and workspace. List them with `organizations list` and `workspaces list --org ORG_ID`, then pass both IDs on scoped commands.

What does --dry-run do?

It prints the request the CLI _would_ send without actually sending it — so you can confirm the body and target before a real mutation.

Why won't my delete run?

Destructive commands require the `--confirm` flag by design. Add `--confirm` once you're sure — it's the safety catch that stops accidental deletions.

Is the CLI different from the API?

It's a thin wrapper over the same public `/api/v1` endpoints. The CLI adds convenience — centralized auth, stable JSON, idempotency handling, and destructive-op confirmation — so agents and scripts don't reimplement it.

Can I keep multiple accounts configured?

Yes — use `--profile <name>` to load a saved local profile, or override `--api-key`/`--base-url` per command to switch between orgs or environments.

## Ready to put this into practice?

Start your FirstSales trial and launch a warmed, authenticated mailbox in minutes.

[Start for $1](https://app.firstsales.io)

[All tutorials](/tutorial/)