Skip to main content

Perspective CLI

perspective is a command-line tool for the Perspective REST API. It is designed to be driven equally well by people, shell scripts, CI jobs and coding agents such as Claude Code:

  • JSON in, JSON out. Every command prints JSON on stdout — pretty-printed at a terminal, compact when piped — so it composes with jq.
  • Machine-readable errors. Errors are printed as JSON on stderr, with a stable exit code.
  • No HTTP client to write. Workspaces, funnels, contacts and metrics are one command each, with pagination and date windows handled for you.
  • Agent-ready. Ships an Agent Skill (SKILL.md) that teaches coding agents how to use it safely.

Install​

Requires Node.js 22.12 or newer.

npm install -g @perspective-software/cli # or: pnpm add -g @perspective-software/cli
perspective --version

To try it without installing, use npx @perspective-software/cli <command>.

Quick start​

# 1. Store your API key (prompts for it)
perspective auth login

# 2. Find a funnel ID
perspective funnels list --status live

# 3. Use it
perspective contacts list <funnelId> --limit 10
perspective metrics kpi <funnelId> conversion_rate --days 30

See Authentication for API keys and CI, and Commands for the full reference.

Output​

Every command that reads or writes API data prints a { "data": … } or { "data": …, "meta": … } envelope. A command that maps to one API request prints the response unchanged (Pagination). A few commands combine or reshape responses, and keep the same envelope:

CommandOutput
funnels listdata is a flat list of funnels: id, name, status, workspaceId, workspaceName.
contacts list --alldata holds the contacts from every page; meta is { "total": n }.
metrics kpi with several KPIs or alldata is a list with one KPI result per item, in the order given, each with its type.

auth and skill commands print their own small objects, such as { "ok": true, … }; see the Command Reference.

perspective funnels list | jq -r '.data[] | "\(.id)\t\(.name)"'

Use --pretty or --no-pretty to override the terminal detection.

To keep output small, --fields keeps only the fields you list. It works on every command, keeps meta, and dotted paths reach into nested objects. A missing field comes back as null, so every item has the same keys:

perspective contacts list <funnelId> --all --fields id,email,status,properties.city

Rate limits​

The API allows 100 requests per minute. When the CLI gets HTTP 429, it waits as long as the Retry-After header says (at most a minute) and retries, up to 3 times, before it fails with exit code 6.

Errors​

Errors go to stderr in one shape:

{
"error": {
"code": "forbidden",
"message": "User has no access to campaign",
"status": 403,
"hint": "Either the funnel ID is wrong or not in a workspace this key can access (check `perspective funnels list`), or the key lacks the permission this endpoint needs (crm:read, crm:write, metrics:read)."
}
}

status is the HTTP status when the error came from the API.

Exit codes​

Codeerror.codeMeaning
0—Success
1errorAny other API error, or an unreadable credentials file
2usageInvalid flags or arguments, or HTTP 400
3unauthenticatedMissing or invalid API key (HTTP 401)
4forbiddenThe funnel ID is wrong or outside your workspaces, or the API key lacks the permission (HTTP 403)
5not_foundUnknown funnel or contact (HTTP 404)
6rate_limitedRate limit hit (HTTP 429) — see Errors
7networkThe API could not be reached or did not answer within 30 seconds

Exit codes are stable across releases, so scripts can branch on them.

Global options​

OptionEnvironment variableDescription
--api-key <key>PERSPECTIVE_API_KEYAPI key
--fields <list>—Only these fields of each result, comma-separated; dots nest
--base-url <url>PERSPECTIVE_BASE_URLAPI origin, default https://api.perspective.co
--pretty / --no-pretty—Force indented / compact JSON
—PERSPECTIVE_CONFIG_DIRWhere the API key is stored, default ~/.config/perspective