SDK v1.12.0
Highlights
Two silent-failure classes eliminated at the SDK and CLI boundary: (1) filter= on companies.list() / persons.list() (and the query command against global entities) now raises instead of silently returning unfiltered data — V2 /companies, /persons, /opportunities never supported server-side filter= and the previous behavior masked this; (2) companies.create() / persons.create() refuse to create a duplicate by default, raising DuplicateEntityError carrying the existing entity ID so callers can recover without producing duplicates.
Breaking Changes
companies.list(),persons.list(), and their.get_first() / .all() / .iter() / .pages()variants now raiseValueErroriffilter=is passed. Previous versions silently returned unfiltered results (V2 API ignores the parameter).queryCLI command:whereclauses oncompanies,persons,opportunitiesnow raiseQueryValidationErrorinstead of silently returning all records. The schema registry'sfilterable_fieldsis empty for these entities. UselistEntrieswith alistIdfilter for list-scoped queries.companies.create()/persons.create()signature adds keyword-onlyif_not_exists: bool = True. Existing callers that expected duplicate-creation must passif_not_exists=Falseexplicitly.- CLI
company create/person createexit with code 6 (duplicate_exists) instead of creating duplicates, unless--allow-duplicateis passed.
What's New
DuplicateEntityErrorexception (subclass ofAffinityError) exposingentity_type,existing_id,existing_name,existing_domain,existing_is_globalcompanies.create(data, *, if_not_exists=True)andpersons.create(data, *, if_not_exists=True)— sync and async. Defaults to pre-checking for duplicates via V1 fuzzy search before POST- CLI
--allow-duplicateflag oncompany create/person createto bypass the pre-check - CLI
duplicate_existserror type (exit code 6) witherror.details.existing.{companyId|personId, name, domain, isGlobal}for recovery - CLI
unsupported_filtererror type (exit code 2) oncompany ls --filter,person ls --filter, andqueryon companies/persons/opportunities
Bug Fixes
- CLI
company ls/person lsno longer forward the--filterargument to the SDK when it isNone, avoiding false positives from the SDK-level rejection. queryCLI errors in--jsonmode now emit a structured error envelope on stdout (parseable by MCP and scripts) witherror.type,error.message,error.hint,error.details.
Quick Install
SDK only:
pip install affinity-sdkSDK + CLI:
pipx install "affinity-sdk[cli]"MCP Server for Claude Desktop (easiest - MCPB bundle):
- Install CLI:
pipx install "affinity-sdk[cli]" - (Optional) Pre-configure API key:
xaffinity config setup-key- If skipped, Claude Desktop will prompt for your API key during install
- Install xaffinity MCP in Claude Desktop (download and double-click)
Other MCP clients (Cursor, Windsurf, VS Code, etc.) require manual configuration - see MCP docs.