Kenso
Kenso CLI

CRM (beta)

Kenso CLI pages

The CRM commands work on Kenso's Accounts lane: accounts (companies), the people on them, and opportunities. They are beta: they need the accounts feature flag on your workspace (opportunities need opportunities, CRM sync needs ingestion). Help and kenso describe hide them until your workspace has the flag; --all-commands shows them.

CommandWhat it does
accounts importCreate accounts from a CSV or JSONL file. Research is charged per created account
people importCreate or match people from a file, optionally onto accounts
accounts update --each, people update --each, opportunities update --eachEdit many records from a file, one call per row
crm-connections, crm-imports, crm-sync-issuesRead and run CRM sync. Connecting a CRM stays in the app

Import accounts first, then people: people import never creates an account.

Import accounts

kenso accounts import --file accounts.csv
kenso accounts import --file accounts.csv --yes
name,domain,industry,employeeCount
Acme,acme.io,Software,120
Globex,globex.com,Manufacturing,"1,200"
  • Columns map by name, ignoring case, spaces and dashes: name (or company, companyName, accountName), domains (several, split on , or ;) or one domain (or website, companyDomain), industry, employeeCount, hqLocation, linkedinUrl, stage, angle, whyNow, fitScore, fundingRound, cadenceDays, ownerMemberId, kenCompanyId, sendsFromInboxId, sendsFromLinkedInAccountId and source.
  • A domain is required. A file with no domain column is a usage error, and a row without a domain is invalid (domain_required).
  • The dry run prices the research. It asks for a credit estimate per 1,000 accounts and puts the sum in the plan: kind, accountCount, totalMillicredits, availableMillicredits and sufficient.
  • Rows go 100 per call to POST /v1/accounts/bulk-create.

Each row comes back:

StatusMeaning
createdA new account; id is the account id. Research is queued (researchQueued in the summary), or waits for credits (researchWaitingCredits)
skipped, reason domain_takenA company that is already an account; id is that account
failedKenso refused the row (reason is the API's code, error names the field) or failed to save it. An item Kenso failed to save is sent once more before it counts as failed

Rerunning the same file is safe: accounts that exist come back domain_taken.

Import people

kenso people import --file people.csv
kenso people import --file people.csv --find-emails --yes
kenso people import --file people.jsonl --dry-run
fullName,email,title,accountDomain,role
Ann Lee,[email protected],VP Sales,acme.io,champion
Bob Ray,,CTO,acme.io,
  • Columns map by name, ignoring case, spaces and dashes: email, fullName (or name), firstName, lastName, title, linkedinUrl (or linkedin, profileUrl), accountDomain (or domain, website, companyDomain), accountId, role and priority. Other columns are ignored with one warning.
  • A person needs a name: fullName, or firstName, lastName or both (the CLI joins them). A row with none of them is invalid (name_required).
  • To put a person on an account, give accountDomain or accountId. A row with both sends only accountId.
  • --find-emails queues an email find (charged in credits) for each person without an email.
  • Rows go 200 per call to POST /v1/people/batch.

People already in the workspace are matched by email, then LinkedIn URL, so running the same file again creates nobody twice.

ResultRow statusreason
A new personcreated
An existing person, added to the accountupdated
An existing person already on the accountskippedalready_on_account
An existing person, no account askedskippedmatched
The person was removed from the account beforeskippedpreviously_removed
The account does not existfailedaccount_not_found: the person was saved without an account. Import the account, then rerun to place them
Kenso refused the rowfailedthe API's reason

The summary adds matched, addedToAccounts and emailFindsQueued.

Edit accounts, people and opportunities

Apart from accounts bulk-update, which sets one accountType on up to 500 accounts, there is no bulk edit route, so run the generated update command once per row with --each. Columns are the command's flags by API name or flag name, and the id column fills the route:

kenso accounts update --each accounts-edit.csv --dry-run
kenso accounts update --each accounts-edit.csv --yes
kenso people update --each people-edit.csv --yes
kenso opportunities update --each deals.csv --yes
accountId,stage,ownerMemberId,overwritePinned
501,engaged,42,true
502,customer,42,true

A row that changes a field someone pinned in the app fails as a whole (409 conflict, pinned_by_user: nothing on that record changes, the other fields of the row included), unless the row sets overwritePinned to true (or you pass --overwrite-pinned). To see every flag of an update command:

kenso describe accounts update
kenso accounts update --help

CRM sync

CRM sync has generated commands only: read connections, preview, start an import, and work through sync issues. Connect the CRM itself in the app.

kenso crm-connections list
kenso crm-connections get --connection-id 7
kenso crm-imports create --connection-id 7 --dry-run
kenso crm-sync-issues list --connection-id 7 --all

Run kenso crm-connections --help (or add --all-commands when the actions are hidden) to see every action.