SightRadardocs

Command-line interface

The sightradar CLI for shells, scripts and coding agents: every API operation as a command, with --json, --dry-run and documented exit codes.

Last updated

Coming soon

sightradar-cli is not on npm yet, so npm install -g sightradar-cli will not work until it publishes. The commands, flags and exit codes on this page are the interface it ships with.
npm install -g sightradar-cli
sightradar --help

The package is sightradar-cli and the command it installs is sightradar. It needs Node.js 20 or newer and has no runtime dependencies. MIT licensed.

Every command has --help with examples, --json prints the API response exactly as returned, and --dry-run prints the request as a curl command without sending it. The agent skill teaches coding agents to use it.

Log in

Create a key in the console. It is shown once. The CLI looks for a key in this order:

  1. The SIGHTRADAR_API_KEY environment variable, the same one the SDKs read.
  2. ~/.config/sightradar/config.json, written by sightradar login. The directory gets mode 0700 and the file 0600. If $XDG_CONFIG_HOME is set, the file lives under it instead.
sightradar login                        # hidden prompt
printenv SR_KEY | sightradar login      # non-interactive: reads the key from stdin
sightradar whoami                       # where the key comes from, and a free check that it works
sightradar logout                       # removes the stored key (does not revoke it)

login reads the key from stdin and never from an argument, so the key stays out of shell history and process lists. It checks the key with a free GET /v1/wallet call before saving; pass --no-verify to skip that. If the stored file is readable by other users, every command warns you and prints the chmod 600 fix.

In CI, set SIGHTRADAR_API_KEY from your secret store and skip login. The variable always wins over the stored key.

Commands

CommandAPICredits
collections create <id>POST /v1/collectionsfree
collections list [--filter t] [--limit n] [--offset n]GET /v1/collectionsfree
collections describe <id>GET /v1/collections/{id}free
collections delete <id> [--immediate | --compliance] [--yes]DELETE /v1/collections/{id}free
collections restore <id>POST /v1/collections/{id}/restorefree
collections deletion-status <id>GET /v1/collections/{id}/deletionfree
index <collection> <image> [--photo-id id]POST /v1/collections/{id}/index93
search <collection> <image> [--threshold 0-1] [--limit n]POST /v1/collections/{id}/search93
search-by-id <collection> <point-id>POST /v1/collections/{id}/search-by-id62
selfies register <collection> <image> --user-id uPOST /v1/collections/{id}/selfies93
compare <source-url> <target-url>POST /v1/compare93 per image
detect <image>POST /v1/detect93
photos delete <collection> <photo-id> [--immediate | --compliance] [--yes]DELETE /v1/collections/{id}/photos/{photoId}free
photos restore <collection> <photo-id>POST /v1/collections/{id}/photos/{photoId}/restorefree
batch submit <collection> [urls...] [--file f] [--wait]POST /v1/batches62 per photo
batch status <batch-id> [--wait]GET /v1/batches/{id}free
batch photos <batch-id> [--all] [--status s]GET /v1/batches/{id}/photosfree
batch list [--limit n]GET /v1/batchesfree
balanceGET /v1/walletfree
usage [--days n]GET /v1/usagefree

Credits follow Billing: per photo processed, never per face, and never for a 4xx or 5xx. Billable commands print the X-Credits-Remaining balance after they run.

The Rekognition names work as aliases: index-faces, search-faces-by-image, search-faces, compare-faces, detect-faces, create-collection, list-collections, describe-collection, delete-collection and delete-faces. sightradar help <command> is the same as <command> --help.

Images

<image> is an https:// URL that SightRadar fetches, a local file the CLI uploads as multipart, or - to read from stdin. --gcs-key <key> takes a Google Cloud Storage object instead. The limit is 30 MB, and the CLI checks local files before sending. compare and batch submit accept URLs (or GCS keys) only, because the API does not take uploads for them. See Images.

Collections

sightradar collections create event-2026
sightradar collections list --filter wedding
sightradar collections describe event-2026 --json | jq .face_count

Index, search and selfies

sightradar index event-2026 ./photos/001.jpg --photo-id 001 --idempotency-key idx-001
sightradar search event-2026 ./selfie.jpg --limit 20 --threshold 0.6
sightradar search event-2026 ./selfie.jpg --json | jq -r '.photo_ids[]'

# Register the selfie once (93 credits), then each search by id costs 62
PID=$(sightradar selfies register event-2026 ./selfie.jpg --user-id u_42 --json | jq -r .point_id)
sightradar search-by-id event-2026 "$PID" --limit 50

--threshold is cosine similarity from 0 to 1, not Rekognition's 0 to 100. Calibrate it on your own photos with the threshold guide. search also takes --embedding-file <path> to search with a precomputed 512-number vector.

Compare and detect

sightradar compare https://example.com/id-photo.jpg https://example.com/selfie.jpg
sightradar compare --source-gcs-key kyc/u42/id.jpg --target-gcs-key kyc/u42/selfie.jpg
sightradar detect ./selfie.jpg                     # exactly one clear face?
curl -s https://cdn.example.com/g/001.jpg | sightradar detect -

Batch

sightradar batch submit event-2026 --file urls.txt --wait
sightradar batch submit event-2026 https://cdn.example.com/1.jpg https://cdn.example.com/2.jpg
sightradar batch photos <batch-id> --all --status failed
sightradar batch list

--file reads one URL per line, url,external_id lines, or a JSON array of {"url", "external_id"} (- reads stdin). Blank lines and # comments are skipped. One submit takes at most 1,000 photos; the CLI refuses larger lists before sending and suggests split -l 1000. --external-id-from-filename sets each external_id from the URL's file name, --op match searches each photo instead of indexing it, and --webhook whe_… sends one signed delivery per photo. The CLI does not register webhooks; see batch and webhooks.

--wait polls the free status endpoint (every 5 seconds, --poll-interval to change) and prints progress to stderr.

Delete and restore

sightradar collections delete event-2026                    # soft, restorable until purge_after
sightradar collections restore event-2026
sightradar collections delete tenant-42 --compliance --yes  # irreversible, audited erasure
sightradar collections deletion-status tenant-42            # done at phase=completed, verified_zero=true
sightradar photos delete event-2026 001                     # one photo's faces, restorable

Deletes are soft by default. --immediate skips the grace window and --compliance also records an audited erasure. Both are irreversible, so the CLI refuses to send either without --yes, and exits 2 with an explanation. --dry-run shows the request without needing --yes. See deleting data.

Account

sightradar balance
sightradar usage --days 7 --json

Machine-readable output

By default output is human-readable text on stdout. With --json, stdout gets the API response body exactly as returned. On failure, stdout is empty and stderr gets one JSON object:

stderr
{
  "error": {
    "status": 402,
    "code": "insufficient_credits",
    "message": "…",
    "hint": "Your wallet is out of credits. Top up or enable auto-recharge…",
    "docs_url": "…"
  }
}

hint is always present and says what to do next. Branch on the exit code first and on code second.

Preview a request with --dry-run

--dry-run prints the HTTP request as a curl command and exits 0. Nothing is sent, nothing is charged, and no API key is needed, so you can check a command before you have an account. The key, if there is one, is shown masked and the printed command reads it from $SIGHTRADAR_API_KEY.

sightradar index event-2026 https://cdn.example.com/1.jpg --photo-id 1 --dry-run
stdout
# dry run: nothing was sent and nothing was charged
curl -X POST https://api.sightradar.com/v1/collections/event-2026/index \
  -H "Authorization: Bearer $SIGHTRADAR_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"url":"https://cdn.example.com/1.jpg","photoId":"1"}'

With --json, the preview is a JSON object with dry_run, method, url, headers and the body.

Retries and idempotency

--retries <n> (default 2, maximum 10) retries 429, 502 and 503 with jittered exponential backoff, and waits for Retry-After when the API sends it. Those statuses are never charged, so retrying them is always safe.

A network error is different: the request may have reached the API and been charged. The CLI retries network errors only for GET requests and for calls that carry --idempotency-key. Pass one on every billable call you might retry:

sightradar index event-2026 ./001.jpg --photo-id 001 --idempotency-key "idx-event-2026-001"

A replay under the same key returns 409 without a second charge. selfies register is the exception: a replay returns the stored point_id with Idempotent-Replay: true. See core concepts.

Global options

OptionDefaultMeaning
--jsonoffAPI response body on stdout; errors as JSON on stderr
--dry-runoffPrint the request as curl and exit. No network call, no charge, no key
--base-url <url>$SIGHTRADAR_BASE_URL or https://api.sightradar.comAPI base URL
--timeout <ms>60000Per-request timeout
--retries <n>2Retries on 429/502/503 (and network errors when safe)
-h, --helpHelp for the command, with examples
--versionPrint the CLI version

Exit codes

ExitMeaning
0OK, including --dry-run
1The API rejected the request (400, 404, 409, 413), or another error
2Usage error: unknown command or option, missing argument, bad value, unreadable local file, unconfirmed irreversible delete
3Auth: no key, 401, or 403
4Out of credits (402)
5Retryable: 429, 502, 503, or a network error
sightradar search event-2026 ./selfie.jpg --json > out.json
case $? in
  0) jq -r '.photo_ids[]' out.json ;;
  4) echo "Top up credits first" ;;
  5) echo "Transient, retry later" ;;
  *) exit 1 ;;
esac

Troubleshooting

On this page