Kenso

Inbox imports

Connect many sending inboxes at once.

Deliverability1 endpointKen-Version: 2026-11-02AuthenticationWorkspacesErrors

Connect up to 500 SMTP/IMAP inboxes in the background and return the import job

POST/v1/inbox-importsinbox-imports.create

Needs the inbox_csv_import feature on your workspace. Until it is on, calls answer 404.

Try it on developer.ken.so

Body rows: 1 to 500 inboxes with the fields of POST /v1/inboxes. Each row runs the same connect (validation, consumer-host guard, white-label mailbox cap, live SMTP AUTH and IMAP LOGIN probe), four at a time. A row with a missing field fails, a row that reuses an earlier row's username on the same smtpHost or imapHost with another password fails, an email an earlier row has is skipped (duplicate_in_file), and an email the workspace already has is skipped (already_exists) unless that inbox is a disconnected SMTP inbox, which the row reconnects. A row logs in before its inbox is created, so a failed probe creates no inbox, and email_in_use (another inbox in Kenso holds the address) is only reported after a successful login. firstName, lastName and dailySendLimit are not applied; set them with PATCH /v1/inboxes/{inboxId}. Returns 202 with the job. Poll GET /v1/jobs/{jobId}?type=inbox_import for inboxImport counts and rows; a job with no progress for 10 minutes fails with error.codeinterrupted. Passwords are never stored or returned. A workspace can have 2 imports queued or running at once; a third gets 409 conflict. Each row that passes the up-front checks takes one unit of a 1,000 per workspace per rolling day limit; an import over it gets 429 quota_exceeded with Retry-After, and nothing runs. Requires delivery edit, the same as POST /v1/inboxes, and the inbox_csv_import feature flag: while it is off for the caller the route answers 404 not_found. Both are checked again before each row: once the flag is off, or the caller is no longer a member with delivery edit, the import stops, every row it had not started is skipped with feature_disabled or forbidden, and the job fails with that error.code.

Parameters

Name
In
Type
Required
Description
Ken-Version
In: header
string, one of: 2026-11-02, 1.1
required
The API version: a dated version (YYYY-MM-DD), or 1.1, another name for the first dated version. Without it the request uses your API key's pinned version; an unpinned key reaches the legacy shape of the same path. 1.0 selects the legacy shape explicitly.
X-Ken-Workspace-Id
In: header
integer (int64)
optional
Workspace to act in. Required when your credential can reach more than one workspace (otherwise 400 workspace_required).

Request body

application/json, optional.

Field
Type
Required
Description
rows
array of CreateInboxImportRow
optional

Response 202

data is a JobModel.

Field
Type
Description
id
integer (int64)
type
string
status
string
progress
JobProgressModel
resource
JobResourceModel
createdAt
string (date-time)
downloadUrl
string
error
JobErrorModel
result
object
Upstream payload for a scraping job get. Omitted for other types and for lists.
domainsListed
integer (int32)
Listed-domain count stored by a completed domain health sweep. Omitted until that count exists.
excludedLibraryContacts
integer (int32)
Contacts from a Kenso library list a contact export left out (they are never exported), including 0. Only on contact_export jobs of kind contacts, campaign and advanced; omitted otherwise.
inboxImport
InboxImportJobModel
Counts and per-row results of an inbox_import job. Passwords are never returned.
personImport
PersonImportJobModel
Counts of a contact_import job with target people: each row created a person, updated (matched) one, or was skipped (no email, LinkedIn URL, or name with a business company domain, or intake refused it).
skipped
ContactImportSkipsModel
Rows a campaign contact_import job skipped, by reason. The duplicate counts name the rule that dropped the row: a contact already in this campaign, a contact in another campaign of the workspace (the campaign dedups against other campaigns), an earlier row of the same import, or the campaign's recently-emailed window.
Request
curl -X POST "https://api.ken.so/v1/inbox-imports" \
  -H "Authorization: Bearer $KEN_API_KEY" \
  -H "Ken-Version: 2026-11-02" \
  -H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID" \
  -H "Content-Type: application/json" \
  -d '{
  "rows": [
    {
      "email": "[email protected]",
      "firstName": "string",
      "lastName": "string",
      "username": "string",
      "password": "string",
      "smtpHost": "string",
      "smtpPort": 1,
      "imapHost": "string",
      "imapPort": 1,
      "smtpStartTls": true,
      "dailySendLimit": 1
    }
  ]
}'
Response 202
{
  "success": true,
  "data": {
    "id": 812,
    "type": "string",
    "status": "string",
    "progress": {
      "completed": 1,
      "total": 1
    },
    "resource": {
      "type": "string",
      "id": 812
    },
    "createdAt": "2026-09-23T15:02:11Z",
    "downloadUrl": "https://example.com",
    "error": {
      "code": "string",
      "message": "string"
    },
    "result": null,
    "domainsListed": 1,
    "excludedLibraryContacts": 1,
    "inboxImport": {
      "connectedCount": 1,
      "failedCount": 1,
      "skippedCount": 1,
      "startedAt": "2026-09-23T15:02:11Z",
      "updatedAt": "2026-09-23T15:02:11Z",
      "completedAt": "2026-09-23T15:02:11Z",
      "rows": [
        {
          "index": 1,
          "email": "[email protected]",
          "status": "string",
          "inboxId": 812,
          "errorCode": "string",
          "message": "string"
        }
      ]
    },
    "personImport": {
      "source": "string",
      "createdCount": 1,
      "updatedCount": 1,
      "skippedCount": 1,
      "startedAt": "2026-09-23T15:02:11Z",
      "completedAt": "2026-09-23T15:02:11Z"
    },
    "skipped": {
      "duplicateInCampaign": 1,
      "duplicateInOtherCampaign": 1,
      "duplicateInSource": 1,
      "alreadyContacted": 1,
      "blocklist": 1,
      "failedValidation": 1,
      "salesNavigatorProfileUnresolved": 1,
      "other": 1,
      "missingKey": 1,
      "invalidEmail": 1,
      "noMx": 1,
      "catchAll": 1,
      "personalEmail": 1,
      "roleAddress": 1,
      "companyContacted": 1,
      "companyCap": 1
    }
  }
}