Commands¶
No-network commands¶
These commands never call the Affinity API:
xaffinity --helpxaffinity completion bash|zsh|fishxaffinity version(alsoxaffinity --version)xaffinity config pathxaffinity config initxaffinity config check-key(reads files, but never calls API)
Configuration¶
xaffinity config path¶
Show the path to the configuration file.
xaffinity config path
xaffinity config init¶
Create a new configuration file with template.
xaffinity config init
xaffinity config init --force # Overwrite existing
xaffinity config check-key¶
Check if an API key is configured. Returns exit code 0 if key found, 1 if not found.
This command checks (in order):
1. AFFINITY_API_KEY environment variable
2. .env file in current directory
3. User config file (config.toml)
xaffinity config check-key
xaffinity config check-key --json
xaffinity config check-key && echo "Key exists"
The --json output includes:
- configured: boolean indicating if a key was found
- source: where the key was found ("environment", "dotenv", "config", or null)
xaffinity config setup-key¶
Securely configure your Affinity API key. Prompts for the key with hidden input (not echoed to screen).
Options:
--scope [project|user]: Where to store the keyproject:.envfile in current directory (auto-added to.gitignore)user: User config file (config.toml, withchmod 600on Unix)--force: Overwrite existing key without confirmation--validate/--no-validate: Test key against API after storing (default: validate)
# Interactive setup (prompts for scope)
xaffinity config setup-key
# Store in current project's .env file
xaffinity config setup-key --scope project
# Store in user config (works across all projects)
xaffinity config setup-key --scope user
# Overwrite existing key
xaffinity config setup-key --force
# Skip API validation
xaffinity config setup-key --no-validate
Get your API key from Affinity API Settings.
Global options¶
These options can be used with any command:
--json/--output json: emit machine-readableCommandResultJSON to stdout.--trace: emit request/response/error trace lines to stderr (safe redaction). Recommended with--no-progressfor long-running commands.--beta: enable beta endpoints (required for merge commands).--session-cache <dir>: enable session caching using the specified directory.--no-cache: disable session caching for this command.
Pipeline Optimization¶
When running multiple CLI commands in a pipeline, you can enable session caching to avoid redundant API calls for metadata like field definitions and list resolution.
Using session commands¶
# Start a session (creates temp cache directory)
export AFFINITY_SESSION_CACHE=$(xaffinity session start)
# Run your commands - metadata is cached across invocations
xaffinity list export "My List" --format json > entries.json
xaffinity field ls --list-id 12345
xaffinity person get 12345
# Check session status
xaffinity session status
# End session (cleanup)
xaffinity session end
unset AFFINITY_SESSION_CACHE
Best practice for scripts (with automatic cleanup)¶
#!/bin/bash
export AFFINITY_SESSION_CACHE=$(xaffinity session start) || exit 1
trap 'xaffinity session end; unset AFFINITY_SESSION_CACHE' EXIT
# Your commands here - cleanup happens automatically on exit, error, or Ctrl+C
xaffinity list export "My List" | jq '.entries[]' | xaffinity person get
Quick one-liner pattern (subshell)¶
For simple pipelines, use a subshell - the session dir is cleaned up by TTL:
(
export AFFINITY_SESSION_CACHE=$(xaffinity session start)
xaffinity list export "My List" | xaffinity person get
)
Cache behavior¶
- Cache is scoped to your API key (multi-tenant safe)
- Default TTL is 10 minutes (configurable via
AFFINITY_SESSION_CACHE_TTL) - Cache is file-based in the specified directory
session endis idempotent - safe to call multiple times
Environment variables¶
| Variable | Description |
|---|---|
AFFINITY_SESSION_CACHE |
Directory for session cache files |
AFFINITY_SESSION_CACHE_TTL |
Cache TTL in seconds (default: 600) |
Session commands¶
| Command | Description |
|---|---|
xaffinity session start |
Create session cache, output path |
xaffinity session end |
Clean up session cache directory |
xaffinity session status |
Show cache stats (entries, size, age) |
Debugging¶
Use --trace to see cache hit/miss information:
xaffinity --trace list export "My List"
# trace #+ cache hit: list_fields_12345
# trace #- cache miss: saved_views_12345
Use --no-cache to bypass session cache:
xaffinity --no-cache list export "My List"
Identity¶
xaffinity whoami¶
Validates credentials and prints tenant/user context.
xaffinity whoami
xaffinity whoami --json | jq
URL resolution¶
xaffinity resolve-url <url>¶
Parses an Affinity UI URL (including tenant hosts like https://<tenant>.affinity.co/... or https://<tenant>.affinity.com/...) and validates it by fetching the referenced object.
xaffinity resolve-url "https://app.affinity.co/companies/263169568"
xaffinity resolve-url "https://mydomain.affinity.com/companies/263169568" --json
People¶
xaffinity person search <query>¶
<query> is a free-text term (typically a name or email address) passed to Affinity's person search.
Options:
--with-interaction-dates: include interaction date data--with-interaction-persons: include persons for interactions--with-opportunities: include associated opportunity IDs--page-size,--cursor,--max-results,--all: pagination options
xaffinity person search "alice@example.com"
xaffinity person search "Alice" --all --json
xaffinity person search "Alice" --with-interaction-dates
xaffinity person ls¶
List persons with V2 pagination. Supports field selection and V2 filter expressions.
Options:
--field <id-or-name>(repeatable): field ID or name to include--field-type <type>(repeatable): field type to include (global, enriched, relationship-intelligence)--filter <expression>: V2 filter expression (custom fields only)--page-size,--cursor,--max-results,--all: pagination options--csv <path>: write CSV output (requires--all)--csv-bom: write UTF-8 BOM for Excel compatibility
Note: --filter only works with custom fields. To filter on built-in properties like type, firstName, etc., use --json output with jq.
xaffinity person ls
xaffinity person ls --page-size 50
xaffinity person ls --field-type enriched --all
xaffinity person ls --filter 'Email =~ "@acme.com"'
xaffinity person ls --all --csv people.csv
xaffinity person ls --all --csv people.csv --csv-bom
See the CSV Export Guide for more details.
xaffinity person get <personSelector>¶
Fetch a person by id, UI URL (including tenant hosts), or a resolver selector.
Examples:
xaffinity person get 26229794
xaffinity person get "https://mydomain.affinity.com/persons/26229794"
xaffinity person get email:alice@example.com
xaffinity person get 'name:"Alice Smith"'
Field selection:
--all-fields: include all supported (non-list-specific) fields.--field <id-or-exact-name>(repeatable)--field-type <type>(repeatable)--no-fields: skip fields entirely.
Expansions:
--expand lists: include lists the person is on (auto-paginates up to a safe cap; use--max-results/--allto adjust).--expand list-entries: include list entries for the person (first page by default; use--max-results/--allto fetch more).--list <id-or-exact-name>: filter list entries to a specific list (requires--expand list-entries).--list-entry-field <id-or-exact-name>(repeatable): project list-entry fields into columns (requires--expand list-entries). Field names are only allowed with--list.--show-list-entry-fields: render per-list-entry Fields tables in human output (requires--expand list-entriesand--max-results <= 3). Mutually exclusive with--list-entry-field.--list-entry-fields-scope list-only|all: control which fields appear in list-entry tables (human output only).
xaffinity person get 26229794 --all-fields --expand lists
xaffinity person get 26229794 --expand list-entries --list "Dealflow" --max-results 200
xaffinity person get 26229794 --expand list-entries --list "Dealflow" --list-entry-field Stage --list-entry-field Amount
xaffinity person get 26229794 --expand list-entries --max-results 1 --show-list-entry-fields
xaffinity person get 26229794 --expand list-entries --max-results 1 --show-list-entry-fields --list-entry-fields-scope all
xaffinity person get 26229794 --all-fields --expand lists --json | jq '.data.person.name'
xaffinity person create¶
xaffinity person create --first-name Ada --last-name Lovelace --email ada@example.com
xaffinity person create --first-name Ada --last-name Lovelace --company-id 224925494
xaffinity person update <personId>¶
xaffinity person update 26229794 --email ada@example.com --email ada@work.com
xaffinity person update 26229794 --first-name Ada --last-name Byron
xaffinity person delete <personId>¶
xaffinity person delete 26229794
xaffinity person merge <primaryId> <duplicateId>¶
xaffinity --beta person merge 111 222
xaffinity person files dump <personId>¶
Downloads all files attached to a person into a folder bundle with a manifest.json.
xaffinity person files dump 12345 --out ./bundle
xaffinity person files upload <personId>¶
Uploads one or more files to a person.
xaffinity person files upload 12345 --file doc.pdf
xaffinity person files upload 12345 --file a.pdf --file b.pdf
Companies¶
xaffinity company search <query>¶
<query> is a free-text term (typically a company name or domain) passed to Affinity's company search.
Options:
--with-interaction-dates: include interaction date data--with-interaction-persons: include persons for interactions--with-opportunities: include associated opportunity IDs--page-size,--cursor,--max-results,--all: pagination options
xaffinity company search "example.com"
xaffinity company search "Example" --json
xaffinity company search "Example" --with-interaction-dates
xaffinity company ls¶
List companies with V2 pagination. Supports field selection and V2 filter expressions.
Options:
--field <id-or-name>(repeatable): field ID or name to include--field-type <type>(repeatable): field type to include (global, enriched, relationship-intelligence)--filter <expression>: V2 filter expression (custom fields only)--page-size,--cursor,--max-results,--all: pagination options--csv <path>: write CSV output (requires--all)--csv-bom: write UTF-8 BOM for Excel compatibility
Note: --filter only works with custom fields. To filter on built-in properties like name, domain, etc., use --json output with jq.
xaffinity company ls
xaffinity company ls --page-size 50
xaffinity company ls --field-type enriched --all
xaffinity company ls --filter 'Industry = "Software"'
xaffinity company ls --all --csv companies.csv
xaffinity company ls --all --csv companies.csv --csv-bom
See the CSV Export Guide for more details.
xaffinity company get <companySelector>¶
Fetch a company by id, UI URL (including tenant hosts), or a resolver selector.
Examples:
xaffinity company get 224925494
xaffinity company get "https://mydomain.affinity.com/companies/224925494"
xaffinity company get domain:wellybox.com
xaffinity company get 'name:"WellyBox"'
Field selection:
--all-fields: include all supported (non-list-specific) fields.--field <id-or-exact-name>(repeatable)--field-type <type>(repeatable)--no-fields: skip fields entirely.
Expansions:
--expand lists: include lists the company is on (auto-paginates up to a safe cap; use--max-results/--allto adjust).--expand list-entries: include list entries for the company (first page by default; use--max-results/--allto fetch more).--expand people: include people associated with the company (use--max-results/--allto control volume).--list <id-or-exact-name>: filter list entries to a specific list (requires--expand list-entries).--list-entry-field <id-or-exact-name>(repeatable): project list-entry fields into columns (requires--expand list-entries). Field names are only allowed with--list.--show-list-entry-fields: render per-list-entry Fields tables in human output (requires--expand list-entriesand--max-results <= 3). Mutually exclusive with--list-entry-field.--list-entry-fields-scope list-only|all: control which fields appear in list-entry tables (human output only).
xaffinity company get 224925494 --all-fields --expand lists
xaffinity company get 224925494 --expand list-entries --list "Dealflow" --max-results 200
xaffinity company get 224925494 --expand list-entries --list "Dealflow" --list-entry-field Stage --list-entry-field Amount
xaffinity company get 224925494 --expand list-entries --max-results 1 --show-list-entry-fields
xaffinity company get 224925494 --expand list-entries --max-results 1 --show-list-entry-fields --list-entry-fields-scope all
xaffinity company get 224925494 --expand people --max-results 50
xaffinity company get 224925494 --all-fields --expand lists --json | jq '.data.company.name'
xaffinity company create¶
xaffinity company create --name "Acme Corp" --domain acme.com
xaffinity company create --name "Acme Corp" --person-id 26229794
xaffinity company update <companyId>¶
xaffinity company update 224925494 --domain acme.com
xaffinity company update 224925494 --person-id 26229794 --person-id 26229795
xaffinity company delete <companyId>¶
xaffinity company delete 224925494
xaffinity company merge <primaryId> <duplicateId>¶
xaffinity --beta company merge 111 222
xaffinity company files dump <companyId>¶
xaffinity company files dump 9876 --out ./bundle
Notes: - Saved files use the original filename when possible; if multiple files share the same name, the CLI disambiguates by appending the file id.
xaffinity company files upload <companyId>¶
Uploads one or more files to a company.
xaffinity company files upload 9876 --file doc.pdf
xaffinity company files upload 9876 --file a.pdf --file b.pdf
Opportunities¶
xaffinity opportunity ls¶
List opportunities (basic v2 representation).
Options:
--page-size,--cursor,--max-results,--all: pagination options--csv <path>: write CSV output (requires--all)--csv-bom: write UTF-8 BOM for Excel compatibility
xaffinity opportunity ls
xaffinity opportunity ls --page-size 200 --all --json
xaffinity opportunity ls --all --csv opportunities.csv
xaffinity opportunity ls --all --csv opportunities.csv --csv-bom
See the CSV Export Guide for more details.
xaffinity opportunity get <opportunitySelector>¶
Fetch an opportunity by id or UI URL (including tenant hosts).
xaffinity opportunity get 123
xaffinity opportunity get "https://mydomain.affinity.com/opportunities/123"
xaffinity opportunity get 123 --details
Notes:
- --details fetches a fuller payload with associations and list entries.
xaffinity opportunity create¶
Create a new opportunity (V1 write path).
xaffinity opportunity create --name "Series A" --list "Dealflow"
xaffinity opportunity create --name "Series A" --list 123 --person-id 1 --company-id 2
xaffinity opportunity update <opportunityId>¶
Update an opportunity (replaces association arrays when provided).
xaffinity opportunity update 123 --name "Series A (Closed)"
xaffinity opportunity update 123 --person-id 1 --person-id 2
xaffinity opportunity delete <opportunityId>¶
xaffinity opportunity delete 123
xaffinity opportunity files upload <opportunityId>¶
Uploads one or more files to an opportunity.
xaffinity opportunity files upload 123 --file doc.pdf
xaffinity opportunity files upload 123 --file a.pdf --file b.pdf
Lists¶
xaffinity list ls¶
xaffinity list ls
xaffinity list ls --all --json
xaffinity list create¶
xaffinity list create --name "Dealflow" --type opportunity --private
xaffinity list create --name "People" --type person --public --owner-id 42
xaffinity list get <list>¶
Accepts a list ID or an exact list name.
The Fields table includes a valueType column using V2 string types (e.g., dropdown-multi, ranked-dropdown).
xaffinity list get 123
xaffinity list get "My Pipeline" --json
xaffinity list export <list>¶
Exports list entries with selected fields. This is the most powerful CSV export command, supporting custom fields and complex filtering.
Options:
--csv <path>: write CSV output--csv-bom: write UTF-8 BOM for Excel compatibility--field <id-or-name>(repeatable): include specific fields--saved-view <name>: use a saved view's field selection--filter <expression>: V1 filter expression
xaffinity list export 123 --csv out.csv
xaffinity list export "My Pipeline" --saved-view "Board" --csv out.csv
xaffinity list export 123 --field Stage --field Amount --filter '"Stage" = "Active"' --csv out.csv
xaffinity list export 123 --csv out.csv --csv-bom
See the CSV Export Guide for more details.
List Entry Commands¶
Shorthand: All list entry commands are also available as top-level entry commands:
xaffinity entry get 123 456 # Same as: xaffinity list entry get 123 456
xaffinity entry set-field 123 456 ... # Same as: xaffinity list entry set-field 123 456 ...
xaffinity list entry add <list>¶
xaffinity list entry add 123 --person-id 26229794
xaffinity list entry add "Dealflow" --company-id 224925494
xaffinity list entry delete <list> <entryId>¶
xaffinity list entry delete 123 98765
xaffinity list entry update-field <list> <entryId>¶
xaffinity list entry update-field 123 98765 --field-id field-123 --value-json '"Active"'
xaffinity list entry batch-update <list> <entryId>¶
xaffinity list entry batch-update 123 98765 --updates-json '{"field-1": "Active", "field-2": 10}'
Notes¶
xaffinity note ls¶
xaffinity note ls
xaffinity note ls --person-id 123 --json
xaffinity note get <noteId>¶
xaffinity note get 9876
xaffinity note create¶
xaffinity note create --content "Met with the team" --person-id 123
xaffinity note create --content "<p>Meeting notes</p>" --type html --company-id 456
xaffinity note update <noteId>¶
xaffinity note update 9876 --content "Updated note content"
xaffinity note delete <noteId>¶
xaffinity note delete 9876
Reminders¶
xaffinity reminder ls¶
xaffinity reminder ls
xaffinity reminder ls --owner-id 42 --status active --json
xaffinity reminder get <reminderId>¶
xaffinity reminder get 12345
xaffinity reminder create¶
xaffinity reminder create --owner-id 42 --type one-time --due-date 2025-01-15T09:00:00Z --person-id 123
xaffinity reminder create --owner-id 42 --type recurring --reset-type interaction --reminder-days 3 --company-id 456
xaffinity reminder update <reminderId>¶
xaffinity reminder update 12345 --content "Follow up after demo"
xaffinity reminder update 12345 --completed
xaffinity reminder delete <reminderId>¶
xaffinity reminder delete 12345
Interactions¶
xaffinity interaction ls¶
xaffinity interaction ls --type email
xaffinity interaction ls --person-id 123 --start-time 2025-01-01T00:00:00Z --end-time 2025-02-01T00:00:00Z
xaffinity interaction get <interactionId>¶
xaffinity interaction get 2468 --type meeting
xaffinity interaction create¶
xaffinity interaction create --type meeting --person-id 123 --content "Met to discuss roadmap" --date 2025-01-10T14:00:00Z
xaffinity interaction create --type email --person-id 123 --content "Intro email" --date 2025-01-05T09:15:00Z --direction outgoing
xaffinity interaction update <interactionId>¶
xaffinity interaction update 2468 --type meeting --content "Updated meeting notes"
xaffinity interaction delete <interactionId>¶
xaffinity interaction delete 2468 --type meeting
Fields¶
xaffinity field ls¶
xaffinity field ls --entity-type company
xaffinity field ls --list-id 123 --json
xaffinity field create¶
xaffinity field create --name "Stage" --entity-type opportunity --value-type dropdown --list-specific
xaffinity field delete <fieldId>¶
xaffinity field delete field-123
xaffinity field history¶
Show field value change history for a specific field on an entity (V1).
xaffinity field history FIELD_ID [OPTIONS]
Arguments:
FIELD_ID(required): Field ID (e.g.,field-123). Usefield ls --list-id LISTto find IDs.
Options:
--person-id <id>: Filter by person--company-id <id>: Filter by company--opportunity-id <id>: Filter by opportunity--list-entry-id <id>: Filter by list entry--action-type <type>: Filter by action (create,update,delete)--max-results <n>: Limit number of results
Exactly one entity selector is required.
xaffinity field history field-123 --person-id 456
xaffinity field history field-123 --company-id 789 --action-type update
xaffinity --json field history field-123 --list-entry-id 101 --max-results 20
Field Values¶
xaffinity field-value ls¶
xaffinity field-value ls --person-id 26229794
xaffinity field-value ls --list-entry-id 98765 --json
xaffinity field-value create¶
xaffinity field-value create --field-id field-123 --entity-id 26229794 --value \"Investor\"
xaffinity field-value update <fieldValueId>¶
xaffinity field-value update 555 --value-json '\"Active\"'
xaffinity field-value delete <fieldValueId>¶
xaffinity field-value delete 555
Relationship Strengths¶
xaffinity relationship-strength get¶
xaffinity relationship-strength get --external-id 26229794
xaffinity relationship-strength get --external-id 26229794 --internal-id 42
Tasks¶
xaffinity task get <taskUrl>¶
xaffinity task get https://api.affinity.co/tasks/person-merges/123
xaffinity task wait <taskUrl>¶
xaffinity task wait https://api.affinity.co/tasks/person-merges/123 --timeout 120