Kenso

Placement tests

The Placement tests endpoints of the Kenso API.

Deliverability3 endpointsKen-Version: 2026-11-02AuthenticationWorkspacesErrors

Requires campaignId. Default sort is -createdAt. Rates are fractions from 0 to 1. Requires ReadAccess. A campaign outside the workspace is not_found.

Parameters

Name
In
Type
Required
Description
CampaignId
In: query
integer (int64)
optional
Campaign whose placement tests to list.
Limit
In: query
integer (int32)
optional
Page size. Defaults to 50. Maximum 200.
Cursor
In: query
string
optional
Opaque cursor from a previous page.
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).

Response 200

data is a list of PlacementTestModel. Each item has these fields. The response also carries pagination.

Field
Type
Description
id
integer (int64)
campaignId
integer (int64)
inboxId
integer (int64)
domainId
integer (int64)
sequenceId
integer (int64)
sequenceVersionId
integer (int64)
status
string
inboxRate
number (double)
spamRate
number (double)
categoryRate
number (double)
missingRate
number (double)
code
string
openPixelHost
string
Host of the campaign open pixel the test sent (openPixel: true on create, DEV-5587). Set on create and on GET /v1/placement-tests/{placementTestId}; omitted when the test carries no pixel.
provider
string
Stored vendor name, such as plusvibe. Omitted when the row has none.
dataPoints
array of PlacementProviderBreakdown
One breakdown derived from stored InboxKit byProvider folder counts. Omitted when no stored provider maps to a screen bucket.
createdAt
string (date-time)
completedAt
string (date-time)
type
string
weekly, on_demand or pre_launch.
startedAt
string (date-time)
When InboxKit started sending the test.
sentCount
integer (int32)
Emails InboxKit sent. 0 when it sent nothing, for example because it refused every sender (see Ken.Scraper.API.Canonical.PlacementTestModel.Errors).
failureReason
string
senderInboxIds
array of integer (int64)
The inboxes the test sent from.
subject
string
The subject sent, with the sample lead's variables filled. Omitted for tests created before it was stored.
body
string
The body sent, filled like Ken.Scraper.API.Canonical.PlacementTestModel.Subject.
counts
PlacementCountsModel
Seed copies per placement. total is their sum.
providers
array of PlacementProviderResultModel
Per seed provider: gmail, google_workspace, outlook, microsoft_365.
senders
array of PlacementSenderResultModel
Per sending mailbox, including one whose mail reached no seed.
seeds
array of PlacementSeedResultModel
One row per seed and sender. Seed addresses are masked.
errors
array of PlacementTestErrorModel
Errors InboxKit reported, such as a sender it does not support.
earlierTests
array of PlacementTestTrendModel
Up to 10 earlier tests of this test's own campaign and domain (whichever are set), newest first. A weekly test shared to another campaign's list still trends with the campaign that owns it; an inbox test without a domain has none.
Request
curl -X GET "https://api.ken.so/v1/placement-tests" \
  -H "Authorization: Bearer $KEN_API_KEY" \
  -H "Ken-Version: 2026-11-02" \
  -H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID"
Response 200
{
  "success": true,
  "data": [
    {
      "id": 812,
      "campaignId": 812,
      "inboxId": 812,
      "domainId": 812,
      "sequenceId": 812,
      "sequenceVersionId": 812,
      "status": "string",
      "inboxRate": 0.5,
      "spamRate": 0.5,
      "categoryRate": 0.5,
      "missingRate": 0.5,
      "code": "string",
      "openPixelHost": "string",
      "provider": "string",
      "dataPoints": [
        {
          "googleWorkspace": 0.5,
          "googlePersonal": 0.5,
          "outlookWorkspace": 0.5,
          "outlookPersonal": 0.5
        }
      ],
      "createdAt": "2026-09-23T15:02:11Z",
      "completedAt": "2026-09-23T15:02:11Z",
      "type": "string",
      "startedAt": "2026-09-23T15:02:11Z",
      "sentCount": 1,
      "failureReason": "string",
      "senderInboxIds": [
        812
      ],
      "subject": "string",
      "body": "string",
      "counts": {
        "inbox": 1,
        "promotions": 1,
        "other": 1,
        "spam": 1,
        "missing": 1,
        "total": 1
      },
      "providers": [
        {
          "provider": "string",
          "inbox": 1,
          "promotions": 1,
          "other": 1,
          "spam": 1,
          "missing": 1,
          "total": 1
        }
      ],
      "senders": [
        {
          "email": "[email protected]",
          "inbox": 1,
          "promotions": 1,
          "other": 1,
          "spam": 1,
          "missing": 1,
          "total": 1
        }
      ],
      "seeds": [
        {
          "seed": "string",
          "provider": "string",
          "senderEmail": "[email protected]",
          "placement": "string",
          "folder": "string",
          "detectedAt": "2026-09-23T15:02:11Z"
        }
      ],
      "errors": [
        {
          "message": "string",
          "at": "2026-09-23T15:02:11Z"
        }
      ],
      "earlierTests": [
        {
          "id": 812,
          "campaignId": 812,
          "inboxId": 812,
          "domainId": 812,
          "status": "string",
          "inboxRate": 0.5,
          "spamRate": 0.5,
          "categoryRate": 0.5,
          "missingRate": 0.5,
          "createdAt": "2026-09-23T15:02:11Z",
          "completedAt": "2026-09-23T15:02:11Z"
        }
      ]
    }
  ],
  "pagination": {
    "nextCursor": "eyJpZCI6ODE1fQ",
    "hasMore": true,
    "total": 1,
    "isTotalCapped": true
  }
}

Requires Delivery edit. Exactly one of domainId or inboxId is required unless randomScope is true. Example: { "campaignId": 812, "inboxId": 44 }. Kenso pays for each test, so each call counts against a per-workspace budget: placementTestCreates (5 a minute, 20 a day, 50 in 30 days; a Free plan gets 1, 2 and 5), over it 429 rate_limited with Retry-After. Where placement_tests_public is on, the budget is placementTestCreatesPublic (2 a day, 8 in 30 days, on every plan), over it 429 quota_exceeded naming the limit, with Retry-After. Super admins are exempt. openPixel: true sends the copy with the campaign open pixel on link. or unsub. of the test's sending domain, whichever serves it; openPixelHost names the host used. No serving host, plain-text copy, or a test with the other pixel setting already running for the campaign and domain is 409 invalid_state.

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
campaignId
integer (int64)
optional
Campaign whose email copy is tested.
inboxId
integer (int64)
optional
Inbox to test. Mutually exclusive with domainId unless randomScope is true.
domainId
integer (int64)
optional
Domain to test. Mutually exclusive with inboxId unless randomScope is true.
sequenceVersionId
integer (int64)
optional
Sequence version to send. Absent uses the live saved copy.
sampleVariables
map of string
optional
Sample values for sequence variables, keyed by variable name.
campaignSegmentId
integer (int64)
optional
contactId
integer (int64)
optional
randomSegment
boolean
optional
randomLead
boolean
optional
randomScope
boolean
optional
randomCopyVersion
boolean
optional
openPixel
boolean
optional
Send the copy with the campaign open pixel, on link. or unsub. of the test's sending domain (whichever serves the pixel first), to compare placement with the pixel on and off. Default false.

Response 201

data is a PlacementTestModel.

Field
Type
Description
id
integer (int64)
campaignId
integer (int64)
inboxId
integer (int64)
domainId
integer (int64)
sequenceId
integer (int64)
sequenceVersionId
integer (int64)
status
string
inboxRate
number (double)
spamRate
number (double)
categoryRate
number (double)
missingRate
number (double)
code
string
openPixelHost
string
Host of the campaign open pixel the test sent (openPixel: true on create, DEV-5587). Set on create and on GET /v1/placement-tests/{placementTestId}; omitted when the test carries no pixel.
provider
string
Stored vendor name, such as plusvibe. Omitted when the row has none.
dataPoints
array of PlacementProviderBreakdown
One breakdown derived from stored InboxKit byProvider folder counts. Omitted when no stored provider maps to a screen bucket.
createdAt
string (date-time)
completedAt
string (date-time)
type
string
weekly, on_demand or pre_launch.
startedAt
string (date-time)
When InboxKit started sending the test.
sentCount
integer (int32)
Emails InboxKit sent. 0 when it sent nothing, for example because it refused every sender (see Ken.Scraper.API.Canonical.PlacementTestModel.Errors).
failureReason
string
senderInboxIds
array of integer (int64)
The inboxes the test sent from.
subject
string
The subject sent, with the sample lead's variables filled. Omitted for tests created before it was stored.
body
string
The body sent, filled like Ken.Scraper.API.Canonical.PlacementTestModel.Subject.
counts
PlacementCountsModel
Seed copies per placement. total is their sum.
providers
array of PlacementProviderResultModel
Per seed provider: gmail, google_workspace, outlook, microsoft_365.
senders
array of PlacementSenderResultModel
Per sending mailbox, including one whose mail reached no seed.
seeds
array of PlacementSeedResultModel
One row per seed and sender. Seed addresses are masked.
errors
array of PlacementTestErrorModel
Errors InboxKit reported, such as a sender it does not support.
earlierTests
array of PlacementTestTrendModel
Up to 10 earlier tests of this test's own campaign and domain (whichever are set), newest first. A weekly test shared to another campaign's list still trends with the campaign that owns it; an inbox test without a domain has none.
Request
curl -X POST "https://api.ken.so/v1/placement-tests" \
  -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 '{
  "campaignId": 812,
  "inboxId": 812,
  "domainId": 812,
  "sequenceVersionId": 812,
  "sampleVariables": {
    "key": "string"
  },
  "campaignSegmentId": 812,
  "contactId": 812,
  "randomSegment": true,
  "randomLead": true,
  "randomScope": true,
  "randomCopyVersion": true,
  "openPixel": true
}'
Response 201
{
  "success": true,
  "data": {
    "id": 812,
    "campaignId": 812,
    "inboxId": 812,
    "domainId": 812,
    "sequenceId": 812,
    "sequenceVersionId": 812,
    "status": "string",
    "inboxRate": 0.5,
    "spamRate": 0.5,
    "categoryRate": 0.5,
    "missingRate": 0.5,
    "code": "string",
    "openPixelHost": "string",
    "provider": "string",
    "dataPoints": [
      {
        "googleWorkspace": 0.5,
        "googlePersonal": 0.5,
        "outlookWorkspace": 0.5,
        "outlookPersonal": 0.5
      }
    ],
    "createdAt": "2026-09-23T15:02:11Z",
    "completedAt": "2026-09-23T15:02:11Z",
    "type": "string",
    "startedAt": "2026-09-23T15:02:11Z",
    "sentCount": 1,
    "failureReason": "string",
    "senderInboxIds": [
      812
    ],
    "subject": "string",
    "body": "string",
    "counts": {
      "inbox": 1,
      "promotions": 1,
      "other": 1,
      "spam": 1,
      "missing": 1,
      "total": 1
    },
    "providers": [
      {
        "provider": "string",
        "inbox": 1,
        "promotions": 1,
        "other": 1,
        "spam": 1,
        "missing": 1,
        "total": 1
      }
    ],
    "senders": [
      {
        "email": "[email protected]",
        "inbox": 1,
        "promotions": 1,
        "other": 1,
        "spam": 1,
        "missing": 1,
        "total": 1
      }
    ],
    "seeds": [
      {
        "seed": "string",
        "provider": "string",
        "senderEmail": "[email protected]",
        "placement": "string",
        "folder": "string",
        "detectedAt": "2026-09-23T15:02:11Z"
      }
    ],
    "errors": [
      {
        "message": "string",
        "at": "2026-09-23T15:02:11Z"
      }
    ],
    "earlierTests": [
      {
        "id": 812,
        "campaignId": 812,
        "inboxId": 812,
        "domainId": 812,
        "status": "string",
        "inboxRate": 0.5,
        "spamRate": 0.5,
        "categoryRate": 0.5,
        "missingRate": 0.5,
        "createdAt": "2026-09-23T15:02:11Z",
        "completedAt": "2026-09-23T15:02:11Z"
      }
    ]
  }
}

Return one placement test with its full results

GET/v1/placement-tests/{placementTestId}placement-tests.get

Try it on developer.ken.so

Adds what the list leaves out: type, startedAt, sentCount, senderInboxIds, the subject and body sent, counts, per providers, per senders, per seeds (masked addresses), InboxKit errors, and up to 10 earlierTests of the test's own campaign and domain (whichever are set) for a trend; a shared weekly test trends with the campaign that owns it, and an inbox test without a domain has none. Result fields are omitted until the test completes. Rates are fractions from 0 to 1. Requires ReadAccess. A test outside the workspace is not_found.

Parameters

Name
In
Type
Required
Description
placementTestId
In: path
integer (int64)
required
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).

Response 200

data is a PlacementTestModel.

Field
Type
Description
id
integer (int64)
campaignId
integer (int64)
inboxId
integer (int64)
domainId
integer (int64)
sequenceId
integer (int64)
sequenceVersionId
integer (int64)
status
string
inboxRate
number (double)
spamRate
number (double)
categoryRate
number (double)
missingRate
number (double)
code
string
openPixelHost
string
Host of the campaign open pixel the test sent (openPixel: true on create, DEV-5587). Set on create and on GET /v1/placement-tests/{placementTestId}; omitted when the test carries no pixel.
provider
string
Stored vendor name, such as plusvibe. Omitted when the row has none.
dataPoints
array of PlacementProviderBreakdown
One breakdown derived from stored InboxKit byProvider folder counts. Omitted when no stored provider maps to a screen bucket.
createdAt
string (date-time)
completedAt
string (date-time)
type
string
weekly, on_demand or pre_launch.
startedAt
string (date-time)
When InboxKit started sending the test.
sentCount
integer (int32)
Emails InboxKit sent. 0 when it sent nothing, for example because it refused every sender (see Ken.Scraper.API.Canonical.PlacementTestModel.Errors).
failureReason
string
senderInboxIds
array of integer (int64)
The inboxes the test sent from.
subject
string
The subject sent, with the sample lead's variables filled. Omitted for tests created before it was stored.
body
string
The body sent, filled like Ken.Scraper.API.Canonical.PlacementTestModel.Subject.
counts
PlacementCountsModel
Seed copies per placement. total is their sum.
providers
array of PlacementProviderResultModel
Per seed provider: gmail, google_workspace, outlook, microsoft_365.
senders
array of PlacementSenderResultModel
Per sending mailbox, including one whose mail reached no seed.
seeds
array of PlacementSeedResultModel
One row per seed and sender. Seed addresses are masked.
errors
array of PlacementTestErrorModel
Errors InboxKit reported, such as a sender it does not support.
earlierTests
array of PlacementTestTrendModel
Up to 10 earlier tests of this test's own campaign and domain (whichever are set), newest first. A weekly test shared to another campaign's list still trends with the campaign that owns it; an inbox test without a domain has none.
Request
curl -X GET "https://api.ken.so/v1/placement-tests/812" \
  -H "Authorization: Bearer $KEN_API_KEY" \
  -H "Ken-Version: 2026-11-02" \
  -H "X-Ken-Workspace-Id: $KEN_WORKSPACE_ID"
Response 200
{
  "success": true,
  "data": {
    "id": 812,
    "campaignId": 812,
    "inboxId": 812,
    "domainId": 812,
    "sequenceId": 812,
    "sequenceVersionId": 812,
    "status": "string",
    "inboxRate": 0.5,
    "spamRate": 0.5,
    "categoryRate": 0.5,
    "missingRate": 0.5,
    "code": "string",
    "openPixelHost": "string",
    "provider": "string",
    "dataPoints": [
      {
        "googleWorkspace": 0.5,
        "googlePersonal": 0.5,
        "outlookWorkspace": 0.5,
        "outlookPersonal": 0.5
      }
    ],
    "createdAt": "2026-09-23T15:02:11Z",
    "completedAt": "2026-09-23T15:02:11Z",
    "type": "string",
    "startedAt": "2026-09-23T15:02:11Z",
    "sentCount": 1,
    "failureReason": "string",
    "senderInboxIds": [
      812
    ],
    "subject": "string",
    "body": "string",
    "counts": {
      "inbox": 1,
      "promotions": 1,
      "other": 1,
      "spam": 1,
      "missing": 1,
      "total": 1
    },
    "providers": [
      {
        "provider": "string",
        "inbox": 1,
        "promotions": 1,
        "other": 1,
        "spam": 1,
        "missing": 1,
        "total": 1
      }
    ],
    "senders": [
      {
        "email": "[email protected]",
        "inbox": 1,
        "promotions": 1,
        "other": 1,
        "spam": 1,
        "missing": 1,
        "total": 1
      }
    ],
    "seeds": [
      {
        "seed": "string",
        "provider": "string",
        "senderEmail": "[email protected]",
        "placement": "string",
        "folder": "string",
        "detectedAt": "2026-09-23T15:02:11Z"
      }
    ],
    "errors": [
      {
        "message": "string",
        "at": "2026-09-23T15:02:11Z"
      }
    ],
    "earlierTests": [
      {
        "id": 812,
        "campaignId": 812,
        "inboxId": 812,
        "domainId": 812,
        "status": "string",
        "inboxRate": 0.5,
        "spamRate": 0.5,
        "categoryRate": 0.5,
        "missingRate": 0.5,
        "createdAt": "2026-09-23T15:02:11Z",
        "completedAt": "2026-09-23T15:02:11Z"
      }
    ]
  }
}