NAV
shell Javascript Ruby Python

Overview

Introduction

API requests are relative to https://api.kit.com/

Welcome to the Kit V4 API.

We're thrilled that you want to help expand our ever-growing platform! Our API offers a host of functionality to help our creators automate a bunch of tasks to help make their lives as easy as possible, especially by helping link their tech marketing stack together in perfect harmony.

As long as the authenticated account's plan is eligible for use with the API and integrations, you will be able to create and send broadcasts to your subscribers, manage your email list through tags and custom fields, import purchase data from your favourite e-commerce platforms and much, much more.

If you are a third party developer, once your app is complete, you will be able to publish it to the thousands of creators using our platform today.

For an overview of apps at Kit, please check out our help centre articles that guide you through the creation of your app, its API access and plugin setup.

If you were previously using the Kit API V3 and want to update to use our new functionality, please review our changelog for breaking changes between versions.

You can also view our Postman Collection here.

Changes

The Kit API V4 introduces many new features and improved functionality from our previous versions such as:

See our guide on upgrading from V3 to V4.

Authentication

We support two authentication mechanisms in the V4 API:

API Keys

To use API Key authentication, first create a V4 API Key in your developer settings.

curl -X GET https://api.kit.com/v4/account \
  -H 'Accept: application/json' \
  -H 'X-Kit-Api-Key: kit_abc123'

Then you can pass the key in the X-Kit-Api-Key header when making requests.

The following endpoints do not support API Key authentication and must be used with OAuth:

OAuth

Authorization URL: https://app.kit.com/oauth/authorize
        Token URL: https://app.kit.com/oauth/token

You can set up your OAuth API Access in your developer settings. If you don't see an option to configure apps, please reach out to us.

When configuring your App for API Access, you'll need to provide an "Authorization URL". This should be a URL on your system that we will link to during app installation so you can initiate OAuth and store the returned access tokens. We will link the user to this URL with a redirect query param, e.g. ?redirect=https://app.kit.com/apps. When the authorization flow is complete, you need to redirect the user back to that provided redirect URL so they can continue their session within the Kit app.

We support the Authorization Code Grant and depending on the type of app your building we support two ways of issuing access tokens:

Install Flow for an App with API Access

Bulk & Async Processing

We support bulk processing for some common use cases, e.g. create subscribers.

These endpoints exist in the bulk namespace, i.e. https://api.kit.com/v4/bulk/.

In our bulk requests, we support synchronous processing for small batch sizes. The cut off size is clearly documented in each bulk request's documentation below.

For large batch sizes, we use an asynchronous callback design. If you include a callback_url in your request body, we’ll POST to that URL when our processing has completed. Our POST request body will be the same response shape as our documented our synchronous 200 OK use case for each endpoint.

If you try to enqueue too many bulk requests at once, you'll receive an error response with a 413 status code, which your code should gracefully handle. Try again after a short period.

Responses & Error Codes

Pagination

curl -X GET https://api.kit.com/v4/broadcasts?per_page=100 \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN_HERE'

All of our list endpoints are paginated unless noted otherwise.

{
  "broadcasts": [...],
  "pagination": {
    "has_previous_page": false,
    "has_next_page": true,
    "start_cursor": "WzEzXQ==",
    "end_cursor": "WzE0XQ==",
    "per_page": 100
  }
}

We provide cursor based pagination.

All paginated endpoints will return a pagination object in the JSON response.

curl -X GET https://api.kit.com/v4/broadcasts?after=WzE0XQ== \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN_HERE'

The default page size is 500 results. To change the page size, use the per_page query parameter. The maximum page size allowed is 1000.

To request the next page of results, use the after query param with the end_cursor value of the response.

curl -X GET https://api.kit.com/v4/broadcasts?before=WzE0XQ== \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN_HERE'

To request the previous page of results, use the before query param with the start_cursor value of the response.

To request the total count of the collection, use the include_total_count query param with a value of true. This will complete another data query to return the total count. Expect a slightly slower response when using this option.

Dates

All dates are returned in UTC, ISO8601 format such as: "2023-07-17T16:48:20Z".

Bad Data

When you create or update a field, you may receive an error response with status code 422 if any fields contain bad data or required fields are missing.

Rate Limiting

We have different rate limits depending on the authentication strategy used: - When using OAuth, no more than 600 requests over a rolling 60 second period for given access token. - When using API Keys, no more than 120 requests over a rolling 60 second period for a given API Key.

If your request rate exceeds our limits, you will receive an error response with status code 429, which your code should gracefully handle. We recommend spacing out your requests and performing an exponential backoff to keep within the limit.

Internal Server Errors

If the server is overloaded or you encounter a bug, you will receive a response with status code 500. Try again after a short period, and if you continue to encounter an error, please raise the issue with support.

Explanation

Double opt-in

With a double opt-in, your subscribers will receive an Incentive Email asking them to click a button to confirm that they wish to be on your email list.

Double opt-in protects your list and your deliverability, making sure your emails reach those who truly want to receive them. This can lead to more engaged subscribers and qualified leads. To learn more about double opt-in view our knowledge base here.

Subscriber states (details on subscriber states can be found here)

In order to confirm an inactive subscriber through double opt-in successfully the subscriber must start in an inactive state. An inactive subscriber transitions from inactive to active by adding the subscriber to a form with double opt-in enabled.

Guides

Upgrading to V4

Accounts

Broadcasts

Subscribers

Custom Fields

Forms

Purchases

Sequences

Tags

Webhooks

OAuth Web Server App Flow

1. User initiates install from Kit's App Store

https://example.com/kit/oauth?redirect=https://app.kit.com/apps/1?success=true

When a user installs your app from the App Store, Kit redirects them to the Authorization URL you've configured.

From here, your app should present the user a screen to sign in (or sign up).

2. App requests user's Kit identity

After the user successfully authenticates with your app, redirect them to Kit's OAuth server to request their identity.

GET https://app.kit.com/oauth/authorize

Example redirect

https://app.kit.com/oauth/authorize?
  client_id=YOUR_CLIENT_ID&
  response_type=code&
  redirect_uri=https://oauth2.example.com/callback&
  state=DEF456

Parameters

Query Parameters
client_idrequired
string
Your app's Client ID
response_typerequired
string
code
redirect_urirequired
string
URI to redirect to
scope
string
Default scope is public. Fine-grained access control via scopes coming soon.
state
string
Custom state to pass to the redirect_uri and/or to protect from XSRF
tenant_name
string
Unique, human-readable identifier for a tenant of a multi-tenant app.

Kit will present a consent screen that asks the user to grant or refuse your app access to their account.

4. Kit redirects to App OAuth callback with authorization code

Example redirect

https://oauth2.example.com/callback?
  code=mrApixZzMPnYO28KoeIZxn2mvom1Tx48S9iyrQVYVE8&
  state=DEF456

If the user grants access, Kit redirects the user back to the redirect_uri you provided when requesting the user's identity in step 2.

Kit appends a code query param with a temporary authorization code.

5. App exchanges authorization code for refresh and access tokens

Your app uses the authorization code provided to obtain a refresh and access token.

POST https://app.kit.com/oauth/token

Body parameter

{
  "client_id": "YOUR_CLIENT_ID",
  "client_secret": "YOUR_CLIENT_SECRET",
  "grant_type": "authorization_code",
  "code": "abc123",
  "redirect_uri": "https://oauth2.example.com/callback"
}

Code samples

# You can also use wget
curl -X POST https://app.kit.com/oauth/token \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -d '{
    "client_id": "YOUR_CLIENT_ID",
    "client_secret": "YOUR_CLIENT_SECRET",
    "grant_type": "authorization_code",
    "code": "abc123",
    "redirect_uri": "https://oauth2.example.com/callback"
  }'
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json'
};
const inputBody = '{
  "client_id": "YOUR_CLIENT_ID",
  "client_secret": "YOUR_CLIENT_SECRET",
  "grant_type": "authorization_code",
  "code": "abc123",
  "redirect_uri": "https://oauth2.example.com/callback"
}';

fetch('https://app.kit.com/oauth/token',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});
require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json'
}
payload = {
  "client_id" => "YOUR_CLIENT_ID",
  "client_secret" => "YOUR_CLIENT_SECRET",
  "grant_type" => "authorization_code",
  "code" => "abc123",
  "redirect_uri" => "https://oauth2.example.com/callback"
}

result = RestClient.post 'https://app.kit.com/oauth/token', payload,
  params: {
  }, headers: headers

p JSON.parse(result)
import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}
json = {
  "client_id": "YOUR_CLIENT_ID",
  "client_secret": "YOUR_CLIENT_SECRET",
  "grant_type": "authorization_code",
  "code": "abc123",
  "redirect_uri": "https://oauth2.example.com/callback"
}

r = requests.post('https://app.kit.com/oauth/token', headers = headers, json = json)

print(r.json())

Parameters

Request Body Schema: application/json
client_idrequired
string
Your app's Client ID
client_secretrequired
string
Your app's Client Secret
grant_typerequired
string
authorization_code
code
string
The code received via the redirect uri query params
redirect_uri
string
The redirect URI the request is coming from (must be one of your app's redirect URIs)

Example responses

200 Response

{
  "access_token": "YOUR_ACCESS_TOKEN_HERE",
  "token_type": "Bearer",
  "expires_in": 172800,
  "refresh_token": "YOUR_REFRESH_TOKEN_HERE",
  "scope": "public",
  "created_at": 1710270147
}

Responses

200

Returns a token

Response Schema: application/json
access_tokenrequired
string
Access token that can be used to make API requests on behalf of the authenticated user
token_typerequired
string
Bearer
expires_inrequired
integer
When the access token expire in seconds
refresh_tokenrequired
string
Refresh token that can be used to generate a new access token once this one expires
scoperequired
string
The scopes available for the access token
created_atrequired
integer
When the access token was created

6. App redirects user back to Kit

Now that the user has completed the OAuth flow, your app must send the the user back to Kit using the redirect parameter provided at the beginning of the flow.

This will ensure the user properly navigates back to your app inside of Kit and registers that the app has been installed.

7. App uses access token to make Kit API calls

Code samples

curl -X GET https://api.kit.com/v4/account \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN_HERE'
const headers = {
  'Accept':'application/json',
  'Authorization':'Bearer YOUR_ACCESS_TOKEN_HERE'
};

fetch('https://api.kit.com/v4/account',
{
  method: 'GET',
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});
require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

result = RestClient.get 'https://api.kit.com/v4/account',
  params: {
  }, headers: headers

p JSON.parse(result)
import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

r = requests.get('https://api.kit.com/v4/account', headers = headers)

print(r.json())

Your app can now make calls to Kit's API on behalf of the user by passing a Authorization header with the token as a Bearer value.

8. App uses refresh token to obtain new access token after expiration

The access token will eventually expire and a new one must be obtained using the refresh token obtained earlier.

POST /oauth/token

Body parameter

{
  "client_id": "YOUR_CLIENT_ID",
  "grant_type": "refresh_token",
  "refresh_token": "abc123"
}

Code samples

# You can also use wget
curl -X POST https://app.kit.com/oauth/token \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -d '{
    "client_id": "YOUR_CLIENT_ID",
    "grant_type": "refresh_token",
    "code": "abc123"
  }'
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json'
};
const inputBody = '{
  "client_id": "YOUR_CLIENT_ID",
  "grant_type": "refresh_token",
  "code": "abc123"
}';

fetch('https://app.kit.com/oauth/token',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});
require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json'
}
payload = {
  "client_id" => "YOUR_CLIENT_ID",
  "grant_type" => "refresh_token",
  "code" => "abc123"
}

result = RestClient.post 'https://app.kit.com/oauth/token', payload,
  params: {
  }, headers: headers

p JSON.parse(result)
import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}
json = {
  "client_id": "YOUR_CLIENT_ID",
  "grant_type": "refresh_token",
  "code": "abc123"
}

r = requests.post('https://app.kit.com/oauth/token', headers = headers, json = json)

print(r.json())

Parameters

Request Body Schema: application/json
client_idrequired
string
Your app's Client ID
grant_typerequired
string
refresh_token
refresh_tokenrequired
string
The refresh token

Example responses

200 Response

{
  "access_token": "YOUR_NEW_ACCESS_TOKEN_HERE",
  "token_type": "Bearer",
  "expires_in": 7200,
  "refresh_token": "YOUR_NEW_REFRESH_TOKEN_HERE",
  "scope": "public",
  "created_at": 1710271006
}

Responses

200

Returns a token

Response Schema: application/json
access_tokenrequired
string
Access token that can be used to make API requests on behalf of the authenticated user
token_typerequired
string
Bearer
expires_inrequired
integer
When the access token expire in seconds
refresh_tokenrequired
string
Refresh token that can be used to generate a new access token once this one expires
scoperequired
string
The scopes available for the access token
created_atrequired
integer
When the access token was created

OAuth SPA & Mobile App Flow

1. User initiates install from Kit's App Store

https://example.com/kit/oauth?redirect=https://app.kit.com/apps/1?success=true

When a user installs your app from the App Store, Kit redirects them to the Authorization URL you've configured.

From here, your app should present the user a screen to sign in (or sign up).

2. App generates code verifier and challenge

Before redirecting the user to the authorization server, the app must first generate a secret code verifier and challenge.

The code verifier is a cryptographically random string using the characters A-Z, a-z, 0-9, and the punctuation characters -._~ (hyphen, period, underscore, and tilde), between 43 and 128 characters long.

Once the app has generated the code verifier, it uses that to create the code challenge. The code challenge is a BASE64-URL-encoded string of the SHA256 hash of the code verifier.

The app will need to store the code_verifier for later use.

3. App requests user's Kit identity

After the user successfully authenticates with your app and the code verifier and challenge have been generated, redirect them to Kit's OAuth server to request their identity.

GET https://app.kit.com/oauth/authorize

Example redirect

https://app.kit.com/oauth/authorize?
  client_id=YOUR_CLIENT_ID&
  response_type=code&
  redirect_uri=https://oauth2.example.com/callback&
  code_challenge=N2U2ZjNiNDEzZDE4NzkwYzYyYTM5ZjEwMzM1NDUzY2IwYTNlNWM5ODQ2NWQyNGU5ZTdiMjZiY2E4Njc5ZjY3Zg&
  code_challenge_method=S256&
  state=DEF456

Parameters

Query Parameters
client_idrequired
string
Your app's Client ID
response_typerequired
string
code
redirect_urirequired
string
URI to redirect to
code_challengerequired
string
A BASE64-URL-encoded string of the SHA256 hash of the code_verifier
code_challenge_methodrequired
string
S256
scope
string
Default scope is public. Fine-grained access control via scopes coming soon.
state
string
Custom state to pass to the redirect_uri and/or to protect from XSRF
tenant_name
string
Unique, human-readable identifier for a tenant of a multi-tenant app

Kit will present a consent screen that asks the user to grant or refuse your app access to their account.

5. Kit redirects to App OAuth callback with authorization code

Example redirect

https://oauth2.example.com/callback?
  code=mrApixZzMPnYO28KoeIZxn2mvom1Tx48S9iyrQVYVE8&
  state=DEF456

If the user grants access, Kit redirects the user back to the redirect_uri you provided when requesting the user's identity in step 2.

Kit appends a code query param with a temporary authorization code.

6. App exchanges authorization code for refresh and access tokens

Your app uses the authorization code provided to obtain a refresh and access token.

POST https://app.kit.com/oauth/token

Body parameter

{
  "client_id": "YOUR_CLIENT_ID",
  "grant_type": "authorization_code",
  "redirect_uri": "https://oauth.example.com/callback",
  "code": "abc123",
  "code_verifier": "add75a87509bca16dead084e7908824c8373cdeeb28341ae44713a6879f47be8f8fe6edfe9b8fa6917535e"
}

Code samples

# You can also use wget
curl -X POST https://app.kit.com/oauth/token \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -H 'Accept: application/json' \
  -d '{
    "client_id": "YOUR_CLIENT_ID",
    "grant_type": "authorization_code",
    "code": "abc123",
    "code_verifier": "add75a87509bca16dead084e7908824c8373cdeeb28341ae44713a6879f47be8f8fe6edfe9b8fa6917535e"
    "redirect_uri": "https://oauth2.example.com/callback"
  }'
const headers = {
  'Content-Type':'application/x-www-form-urlencoded',
  'Accept':'application/json'
};
const inputBody = '{
  "client_id": "YOUR_CLIENT_ID",
  "grant_type": "authorization_code",
  "redirect_uri": "https://oauth2.example.com/callback",
  "code": "abc123",
  "code_verifier": "add75a87509bca16dead084e7908824c8373cdeeb28341ae44713a6879f47be8f8fe6edfe9b8fa6917535e"
}';

fetch('https://app.kit.com/oauth/token',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});
require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/x-www-form-urlencoded',
  'Accept' => 'application/json'
}
payload = {
  "client_id" => "YOUR_CLIENT_ID",
  "grant_type" => "authorization_code",
  "redirect_uri" => "https://oauth2.example.com/callback",
  "code" => "abc123",
  "code_verifier" => "add75a87509bca16dead084e7908824c8373cdeeb28341ae44713a6879f47be8f8fe6edfe9b8fa6917535e"
}

result = RestClient.post 'https://app.kit.com/oauth/token', payload,
  params: {
  }, headers: headers

p JSON.parse(result)
import requests
headers = {
  'Content-Type': 'application/x-www-form-urlencoded',
  'Accept': 'application/json'
}
json = {
  "client_id": "YOUR_CLIENT_ID",
  "grant_type": "authorization_code",
  "redirect_uri": "https://oauth2.example.com/callback",
  "code": "abc123",
  "code_verifier": "add75a87509bca16dead084e7908824c8373cdeeb28341ae44713a6879f47be8f8fe6edfe9b8fa6917535e"
}

r = requests.post('https://app.kit.com/oauth/token', headers = headers, json = json)

print(r.json())

Parameters

Request Body Schema: application/json
client_idrequired
string
Your app's Client ID
grant_typerequired
string
authorization_code
redirect_urirequired
string
The redirect uri the request is coming from (must be one of your app's redirect
coderequired
string
The code received via the redirect uri query
code_verifierrequired
string
A cryptographically random string using the characters A-Z, a-z, 0-9, and the punctuation characters -._~ (hyphen, period, underscore, and tilde), between 43 and 128 characters long.

Example responses

200 Response

{
  "access_token": "YOUR_ACCESS_TOKEN_HERE",
  "token_type": "Bearer",
  "expires_in": 172800,
  "refresh_token": "YOUR_REFRESH_TOKEN_HERE",
  "scope": "public",
  "created_at": 1710270147
}

Responses

200

Returns a token

Response Schema: application/json
access_tokenrequired
string
Access token that can be used to make API requests on behalf of the authenticated user
token_typerequired
string
Bearer
expires_inrequired
integer
When the access token expire in seconds
refresh_tokenrequired
string
Refresh token that can be used to generate a new access token once this one expires
scoperequired
string
The scopes available for the access token
created_atrequired
integer
When the access token was created

7. App redirects user back to Kit

Now that the user has completed the OAuth flow, your app must send the the user back to Kit using the redirect parameter provided at the beginning of the flow.

This will ensure the user properly navigates back to your app inside of Kit and registers that the app has been installed.

8. App uses access token to make Kit API calls

Code samples

curl -X GET https://api.kit.com/v4/account \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN_HERE'
const headers = {
  'Accept':'application/json',
  'Authorization':'Bearer YOUR_ACCESS_TOKEN_HERE'
};

fetch('https://api.kit.com/v4/account',
{
  method: 'GET',
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});
require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

result = RestClient.get 'https://api.kit.com/v4/account',
  params: {
  }, headers: headers

p JSON.parse(result)
import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

r = requests.get('https://api.kit.com/v4/account', headers = headers)

print(r.json())

Your app can now make calls to Kit's API on behalf of the user by passing a Authorization header with the token as a Bearer value.

9. App uses refresh token to obtain new access token after expiration

The access token will eventually expire and a new one must be obtained using the refresh token obtained earlier.

POST https://app.kit.com/oauth/token

Body parameter

{
  "client_id": "YOUR_CLIENT_ID",
  "grant_type": "refresh_token",
  "refresh_token": "abc123"
}

Code samples

# You can also use wget
curl -X POST https://app.kit.com/oauth/token \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -d '{
    "client_id": "YOUR_CLIENT_ID",
    "grant_type": "refresh_token",
    "code": "abc123"
  }'
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json'
};
const inputBody = '{
  "client_id": "YOUR_CLIENT_ID",
  "grant_type": "refresh_token",
  "code": "abc123"
}';

fetch('https://app.kit.com/oauth/token',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});
require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json'
}
payload = {
  "client_id" => "YOUR_CLIENT_ID",
  "grant_type" => "refresh_token",
  "code" => "abc123"
}

result = RestClient.post 'https://app.kit.com/oauth/token', payload,
  params: {
  }, headers: headers

p JSON.parse(result)
import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}
json = {
  "client_id": "YOUR_CLIENT_ID",
  "grant_type": "refresh_token",
  "code": "abc123"
}

r = requests.post('https://app.kit.com/oauth/token', headers = headers, json = json)

print(r.json())

Parameters

Request Body Schema: application/json
client_idrequired
string
Your app's Client ID
grant_typerequired
string
refresh_token
refresh_tokenrequired
string
The refresh token

Example responses

200 Response

{
  "access_token": "YOUR_NEW_ACCESS_TOKEN_HERE",
  "token_type": "Bearer",
  "expires_in": 7200,
  "refresh_token": "YOUR_NEW_REFRESH_TOKEN_HERE",
  "scope": "public",
  "created_at": 1710271006
}

Responses

200

Returns a token

Response Schema: application/json
access_tokenrequired
string
Access token that can be used to make API requests on behalf of the authenticated user
token_typerequired
string
Bearer
expires_inrequired
integer
When the access token expire in seconds
refresh_tokenrequired
string
Refresh token that can be used to generate a new access token once this one expires
scoperequired
string
The scopes available for the access token
created_atrequired
integer
When the access token was created

Editor Block Plugins

Kit's editor block plugin can help you extend our editing experience by adding your own elements which are generated by endpoints on your server.

To get started, first sign into our app and visit your Developer Settings to create your App, configure your plugin access, and create your plugins.

Each plugin will appear as an item under your company's name in our editor’s element menu. For more details on setting up apps and plugins, visit our app and plugin help center articles

Plugin Flow

Let’s say you were developing an integration that allowed users to embed “Products” from your app inside the Kit editor. The full flow would look like this:

  1. You would create an API endpoint to generate the HTML for your Product embed.
  2. You would create an API endpoint for users to search products in their account
  3. You would create your app and configure the Product plugin in Kit's developer dashboard.
    • Add a name, such as "Product"
    • Configure your settings, such as a search input to find a particular product on the user’s account,
      request_url: https://api.example.com/kit/product
  4. A user would install your app from Kit's App Store
  5. They would complete the authorization process for your site/API and we'll store their authorization data (tokens, etc.)
  6. They open Kit's editor and insert your Product element.
  7. Any time they change its settings, we will make a request to the endpoint from #1.
    • We will include both the editor settings (for instance, the ID of the Product they want to embed) and their API access token, which you can use to validate if they have access.
  8. You will return the HTML for the user’s Product, which we'll insert into our editor.

Plugin Configuration

Example editor block plugin:

Name

The Plugin name is the user-facing name for your block. In the screenshot above, “Post”, and “Product” are examples of labels. It will appear in the editor’s element menu, and also in the breadcrumbs at the top of the sidebar when your block is selected. Your label should be short, ideally one or two words.

Description

The Description is a short phrase describing your block. It will appear underneath the Label in the element menu. In the example above, “Add a link to a post” and “Add a link to a product”.

Sort order

If you offer multiple elements, the Sort Order determines their placement. In the image above, “Post” has a Sort Order of 0, while “Product” has a Sort Order of 1.

The Logo is an image for the element to be displayed alongside the Label and the Description. Only PNG, GIF, JPEG extensions are supported. The recommended size is 150x120px.

HTML URL

Example POST request body sent to your HTML URL

{
  "settings": {
    // The exact data in this section depends on how you've configured your
    // plugin's JSON settings (see next section).
    "title": "My title",
    "description": "My description"
  }
}

The HTML URL is the URL of an endpoint on your server that returns an HTML string. This endpoint’s job is to generate the HTML for your element to be rendered in the email editor.

You’ll generate this HTML based on the settings you’ve defined for your block (outlined in the next section). Once a user completes all required settings, we’ll make a POST request to your HTML URL. The request will contain a settings object with the user’s selected values for each of your settings.

Example ERB to render HTML response

<div>
  <h1><%= @settings[:title] %></h1>
  <p><%= @settings[:description] %></p>
</div>

Your endpoint should return HTML for the element. For instance, if you’re using ERB, it might look like the block to the right.

HTML Success Response

{
  "code": 200,
  "html": "<div>...your HTML...</div>"
}

Your HTML URL should respond to this request with a JSON object containing an html key

HTML Error Response

{
  "code": 404,
  "errors": ["Plan not found"]
}

Or, if you've encountered an error, return an object containing an errors array of strings. You may add as many errors to this array as you’d like:

Settings JSON

Example settings configuration

[
  {
    "type": "text",
    "name": "title",
    "label": "Title",
    "placeholder": "Enter a title...",
    "required": true
  },
  {
    "type": "color",
    "name": "title_color",
    "label": "Color",
    "required": true
  }
]

This field allows you to configure the sidebar settings for your element. It should be an array of objects; one object for each setting. For instance, this would be the JSON configuration for a plugin with two settings: “Title” and “Color”.

Each setting’s type determines the UI rendered (such as a text input or a color picker); all available options are listed under the subheadings below.

The name for each setting is used as the key in your HTML request.

See Editor Block Plugin Settings for all the possible settings you can configure.

JSON schema

{
  "type": "array",
  "items": {
    "anyOf": [
      {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": ["color"]
          },
          "name": {
            "type": "string"
          },
          "label": {
            "type": "string"
          },
          "required": {
            "type": "boolean"
          }
        },
        "required": ["name", "label", "type"],
        "additionalProperties": false
      },
      {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": ["fontFamily"]
          },
          "name": {
            "type": "string"
          },
          "label": {
            "type": "string"
          },
          "required": {
            "type": "boolean"
          }
        },
        "required": ["name", "label", "type"],
        "additionalProperties": false
      },
      {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": ["search"]
          },
          "name": {
            "type": "string"
          },
          "label": {
            "type": "string"
          },
          "request_url": {
            "type": "string"
          },
          "placeholder": {
            "type": "string"
          },
          "required": {
            "type": "boolean"
          }
        },
        "required": ["type", "name", "label", "request_url"],
        "additionalProperties": false
      },
      {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": ["select"]
          },
          "name": {
            "type": "string"
          },
          "label": {
            "type": "string"
          },
          "options": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "value": {
                  "type": "string"
                },
                "label": {
                  "type": "string"
                }
              }
            }
          },
          "placeholder": {
            "type": "string"
          },
          "required": {
            "type": "boolean"
          }
        },
        "required": ["type", "name", "label", "options"],
        "additionalProperties": false
      },
      {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": ["text"]
          },
          "name": {
            "type": "string"
          },
          "label": {
            "type": "string"
          },
          "placeholder": {
            "type": "string"
          },
          "required": {
            "type": "boolean"
          }
        },
        "required": ["name", "label", "type"],
        "additionalProperties": false
      }
    ]
  }
}

How settings JSON maps to the HTML request

When you save your plugin via the developer settings, we’ll validate your JSON settings against the following schema.

Activating your plugin

When you first create your plugin it will be inactive. While inactive it will only be available for your developer account.

Once activated, the plugin will be visible to any user who has installed the app.

If a plugin is actively being used, we don't recommend inactivating and re-activating. Instead, create a new plugin and keep it inactive while making your changes. Once your tests are successful, you can update the original plugin.

Plugin Settings

Color Picker

Use the type: color setting config for a color picker.

Color Picker Setting

{
  "type": "color",
  "name": "background_color",
  "label": "Background color",
  "required": true, // optional
  "help": "help text shown in tooltip to creator while editing" // optional
}

Font Picker

Use the type: fontFamily setting config for a font family and font weight picker. Kit will automatically supply a list of email-friendly font families and their fallbacks.

Font Picker Setting

{
  "type": "fontFamily",
  "name": "paragraph_font",
  "label": "Paragraph font",
  "required": true, // optional
  "help": "help text shown in tooltip to creator while editing" // optional
}

Font family setting example request

{
  "settings": {
    "yourFontFieldName": {
      "fontFamily": "'Courier New', Courier, monospace",
      "fontWeight": 400,
    }
  }
}

When requesting HTML, Kit will pass the user’s values for fontFamily fields as an object with a fontFamily and a fontWeight.

Date Picker

Use the type: date setting config for a date picker.

All dates are returned in UTC, ISO8601 format such as: "2024-10-03T07:00:00.000Z"

Date Picker Setting

{
  "type": "date",
  "name": "start_date",
  "label": "Start date",
  "required": false, // optional
  "help": "help text shown in tooltip to creator while editing" // optional
}

Search Input

Use the type: search setting config for a search input.

When the plugin loads, Kit will make a request to your provided request_url with an empty string search param. This allows you to autopopulate the search dropdown with default results.

When the creator types into the search input, Kit will make a debounced request to your provided request_url to retrieve further filtered results.

If a creator leaves their email in a draft state and edits again in the future, we'll make a request to your provided request_url with the value of the option they had previously selected. This allows us to fill the dropdown with your user-friendly label.

Search Input Setting

{
  "type": "search",
  "name": "post",
  "label": "Post",
  "request_url": "https://example.com/path/to/your/search/endpoint",
  "placeholder": "Select a post", // optional
  "required": true, // optional
  "help": "help text shown in tooltip to creator while editing", // optional
  "dependencies": ["names", "of", "inputs", "to", "depend", "on"], // optional
}

The optional dependencies configuration allows you to wait to display a search input until the creator has entered values for all of the dependency inputs.

Once all the dependencies have a value, your dependent search input will be displayed. And we will include the dependencies as parameters to your provided request_url.

Search setting example request

{
  "search": "Query the user typed"
}

Kit will send a POST request with the following shape to your request_url to retrieve the results:

Search setting example request with configured dependencies

// if this is your search input configuration
{
  "type": "search",
  "name": "post",
  "label": "Post",
  "request_url": "https://example.com/path/to/your/search/endpoint",
  "dependencies": ["favorite_color"], // optional
}

// Kit will send a POST that includes the dependencies
{
  "favorite_color": "value user selected",
  "search": "Query the user typed"
}

Search setting example success response

{
  "data": [
    {
      "label": "A post title",
      "value": "post-id-123"
    }
  ]
}

Search setting example error response

{
  "data": [],
  "errors": ["Plan not found"]
}

You should return an array of objects, each with a label-value pair.

The label will be visible to users; it is used as the text for the result. The value is not visible to users, but will be sent when requesting HTML for your block.

Select Input

Use the type: select setting config for a select input, commonly called a “dropdown menu” with a predefined list of options. The chosen value is not visible to users, but will be sent when requesting HTML for your block.

Select Input Setting

{
  "name": "favorite_food",
  "label": "Favorite food",
  "options": [
    {
      "label": "French fries",
      "value": "food-id-1"
    },
    {
      "label": "Hash browns",
      "value": "food-id-2"
    },
    {
      "label": "Potato chips",
      "value": "food-id-3"
    }
  ],
  "placeholder": "Select a food...", // optional
  "required": true, // optional
  "help": "help text shown in tooltip to creator while editing" // optional
}

Text Input

Use the type: text setting config for a single-line text input useful for entering short snippets of text.

Text Input Setting

{
  "type": "text",
  "name": "title",
  "label": "Title",
  "placeholder": "Enter a title...", // optional
  "required": true, // optional
  "help": "help text shown in tooltip to creator while editing" // optional
}

Required settings

You can optionally add required: true to a setting. We won’t request HTML from your server until all required settings are complete.

Help text

You can optionally add help text for creators when using your plugin. You can add help: "some help text" to any setting and we'll render a tooltip on your input label with your help text.

Refreshing data

After a user has configured all required settings, we will perform a request to your server for the block's HTML. If the user wants to refresh the data, they can either:

  1. Click the refresh button that appears when hovering over the element (pictured below), or
  2. Change one of your plugin’s settings in the sidebar, which will automatically kick off another request for new HTML.

refresh plugin data

Plugin Authorization

We currently support 2 authorization strategies for requesting data from your API.

OAuth Plugin

For OAuth, you'll need to support 4 endpoints

The endpoints must accept the requests outlined below and return responses minimally matching the outlined response shapes (additional attributes can be returned but we require at least what appears in these docs).

The redirect URI we'll use for all of our requests will be https://app.kit.com/apps.

We'll use Bearer Authorization to include the user's access token on all the requests we make to your endpoints.

Get an authorization code grant

Example redirect

<YOUR_CONFIGURED_AUTHORIZATION_URL>?
  client_id=<YOUR CONFIGURED CLIENT ID>&
  response_type=code&
  redirect_uri=https://app.kit.com/apps

Code samples

# You can also use wget
curl -G GET <YOUR CONFIGURED AUTHORIZE URL> \
  -H 'Accept: text/html'
  -d "client_id=<YOUR CONFIGURED CLIENT ID>"
  -d "response_type=code"
  -d "redirect_uri=https://app.kit.com/apps"
const headers = {
  'Accept':'text/html'
};

fetch('<YOUR CONFIGURED AUTHORIZE URL>?client_id=<YOUR CONFIGURED CLIENT ID>&response_type=code&redirect_uri=https://app.kit.com/apps',
{
  method: 'GET',
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});
require 'rest-client'
require 'json'

headers = {
  'Accept' => 'text/html'
}

result = RestClient.get '<YOUR CONFIGURED AUTHORIZE URL>?client_id=<YOUR CONFIGURED CLIENT ID>&response_type=code&redirect_uri=https://app.kit.com/apps',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'text/html'
}

r = requests.get('<YOUR CONFIGURED AUTHORIZE URL>?client_id=<YOUR CONFIGURED CLIENT ID>&response_type=code&redirect_uri=https://app.kit.com/apps', headers = headers)

print(r.json())

GET <YOUR CONFIGURED AUTHORIZE URL>

Parameters

Query Parameters
client_idrequired
string
Your plugin's configured Client ID
response_typerequired
string
code
redirect_urirequired
string
https://app.kit.com/apps
state
string
Custom state to pass to the redirect_uri and/or to protect from XSRF

Example responses

302 Response

"<html><body>You are being <a href=\"https://app.kit.com/apps">redirected</a>.</body></html>"

Responses

302

Redirects to https://app.kit.com/apps with authorization code parameter

Get a new token using an authorization code

Body parameter

{
  "client_id": "<YOUR CONFIGURED CLIENT ID>",
  "client_secret": "<YOUR CONFIGURED CLIENT SECRET>",
  "grant_type": "authorization_code",
  "code": "abc123",
  "redirect_uri": "https://app.kit.com/apps"
}

Code samples

# You can also use wget
curl -X POST <YOUR CONFIGURED TOKEN URL> \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -H 'Accept: application/json' \
  -d '{
    "client_id": "<YOUR CONFIGURED CLIENT ID>",
    "client_secret": "<YOUR CONFIGURED CLIENT SECRET>",
    "grant_type": "authorization_code",
    "code": "abc123",
    "redirect_uri": "https://app.kit.com/apps"
  }
const inputBody = '{
  "client_id": "<YOUR CONFIGURED CLIENT ID>",
  "client_secret": "<YOUR CONFIGURED CLIENT SECRET>",
  "grant_type": "authorization_code",
  "code": "abc123",
  "redirect_uri": "https://app.kit.com/apps"
}';
const headers = {
  'Content-Type':'application/x-www-form-urlencoded',
  'Accept':'application/json'
};

fetch('<YOUR CONFIGURED TOKEN URL>',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});
require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/x-www-form-urlencoded',
  'Accept' => 'application/json'
}
payload = {
  "client_id" => "<YOUR CONFIGURED CLIENT ID>",
  "client_secret" => "<YOUR CONFIGURED CLIENT SECRET>",
  "grant_type" => "authorization_code",
  "code" => "abc123",
  "redirect_uri" => "https://app.kit.com/apps"
}

result = RestClient.post '<YOUR CONFIGURED TOKEN URL>', payload,
  params: {
  }, headers: headers

p JSON.parse(result)
import requests
headers = {
  'Content-Type': 'application/x-www-form-urlencoded',
  'Accept': 'application/json'
}
json = {
  "client_id": "<YOUR CONFIGURED CLIENT ID>",
  "client_secret": "<YOUR CONFIGURED CLIENT SECRET>",
  "grant_type": "authorization_code",
  "code": "abc123",
  "redirect_uri": "https://app.kit.com/apps"
}

r = requests.post('<YOUR CONFIGURED TOKEN URL>', headers = headers, json = json)

print(r.json())

POST <YOUR CONFIGURED TOKEN URL>

Parameters

Request Body Schema: application/json
client_idrequired
string
Your plugin's configured Client ID
client_secretrequired
string
Your plugin's configured Client Secret
grant_typerequired
string
authorization_code
coderequired
string
The code received via the redirect uri query params
redirect_urirequired
string
https://app.kit.com/apps

Example responses

200 Response

{
  "access_token": "YOUR_ACCESS_TOKEN_HERE",
  "expires_in": 172800,
  "refresh_token": "YOUR_REFRESH_TOKEN_HERE",
  "created_at": 1710270147
}

Responses

200

Returns a token

Response Schema: application/json
access_tokenrequired
string
Access token for a user in the plugin app's system
expires_inrequired
integer
When the access token expire in seconds
refresh_tokenrequired
string
Refresh token that can be used to generate a new access token once this one expires
created_atrequired
integer
When the access token was created

Get a new token using a refresh token

Body parameter

{
  "client_id": "<YOUR CONFIGURED CLIENT ID>",
  "grant_type": "refresh_token",
  "refresh_token": "string"
}

Code samples

# You can also use wget
curl -X POST <YOUR CONFIGURED REFRESH TOKEN URL> \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -H 'Accept: application/json' \
  -d '{
    "client_id": "<YOUR CONFIGURED CLIENT ID>",
    "grant_type": "refresh_token",
    "refresh_token": "abc123"
  }'
const inputBody = '{
  "client_id": "<YOUR CONFIGURED CLIENT ID>",
  "grant_type": "refresh_token",
  "refresh_token": "string"
}';
const headers = {
  'Content-Type':'application/x-www-form-urlencoded',
  'Accept':'application/json'
};

fetch('<YOUR CONFIGURED REFRESH TOKEN URL>',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});
require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/x-www-form-urlencoded',
  'Accept' => 'application/json'
}
payload = {
  "client_id" => "<YOUR CONFIGURED CLIENT ID>",
  "grant_type" => "refresh_token",
  "refresh_token" => "abc123"
}

result = RestClient.post '<YOUR CONFIGURED REFRESH TOKEN URL>', payload,
  params: {
  }, headers: headers

p JSON.parse(result)
import requests
headers = {
  'Content-Type': 'application/x-www-form-urlencoded',
  'Accept': 'application/json'
}
json = {
  "client_id": "<YOUR CONFIGURED CLIENT ID>",
  "grant_type": "refresh_token",
  "refresh_token": "abc123"
}

r = requests.post('<YOUR CONFIGURED REFRESH TOKEN URL>', headers = headers, json = json)

print(r.json())

POST <YOUR CONFIGURED REFRESH TOKEN URL>

Parameters

Request Body Schema: application/json
client_idrequired
string
Your plugin's configured Client ID
grant_typerequired
string
refresh_token
refresh_tokenrequired
string
The refresh token

Example responses

200 Response

{
  "access_token": "YOUR_NEW_ACCESS_TOKEN_HERE",
  "expires_in": 7200,
  "refresh_token": "YOUR_NEW_REFRESH_TOKEN_HERE",
  "created_at": 1710271006
}

Responses

200

Returns a token

Response Schema: application/json
access_tokenrequired
string
Access token for a user in the plugin app's system
expires_inrequired
integer
When the access token expire in seconds
refresh_tokenrequired
string
Refresh token that can be used to generate a new access token once this one expires
created_atrequired
integer
When the access token was created

Revoke an access token

Body parameter

{
  "client_id": "<YOUR CONFIGURED CLIENT ID>",
  "client_secret": "<YOUR CONFIGURED CLIENT SECRET>",
  "token": "abc123"
}

Code samples

# You can also use wget
curl -X POST <YOUR CONFIGURED REVOKE TOKEN URL> \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -H 'Accept: application/json' \
  -d '{
    "client_id": "<YOUR CONFIGURED CLIENT ID>",
    "client_secret": "<YOUR CONFIGURED CLIENT SECRET>",
    "token": "abc123"
  }'
const inputBody = '{
  "client_id": "<YOUR CONFIGURED CLIENT ID>",
  "client_secret": "<YOUR CONFIGURED CLIENT SECRET>",
  "token": "string"
}';
const headers = {
  'Content-Type':'application/x-www-form-urlencoded',
  'Accept':'application/json'
};

fetch('<YOUR CONFIGURED REVOKE TOKEN URL>',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});
require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/x-www-form-urlencoded',
  'Accept' => 'application/json'
}
payload = {
  "client_id" => "<YOUR CONFIGURED CLIENT ID>",
  "client_secret" => "<YOUR CONFIGURED CLIENT SECRET>",
  "token" => "abc123"
}

result = RestClient.post '<YOUR CONFIGURED REVOKE TOKEN URL>', payload,
  params: {
  }, headers: headers

p JSON.parse(result)
import requests
headers = {
  'Content-Type': 'application/x-www-form-urlencoded',
  'Accept': 'application/json'
}
json = {
  "client_id": "<YOUR CONFIGURED CLIENT ID>",
  "client_secret": "<YOUR CONFIGURED CLIENT SECRET>",
  "token": "abc123",
}

r = requests.post('<YOUR CONFIGURED REVOKE TOKEN URL>', headers = headers, json = json)

print(r.json())

POST <YOUR CONFIGURED REVOKE TOKEN URL>

Parameters

Request Body Schema: application/json
client_idrequired
string
Your plugin's configured Client ID
client_secretrequired
string
Your plugin's configured Client Secret
tokenrequired
string
The access token

Example responses

200 Response

{}

Responses

200

OK

OAuth Plugin Example

Coming soon!

Plugin Security

We receive an HTML string from your server. We will sanitize it to conform with recommended security practices. That means we’ll reject your HTML response if it includes any of the following:

Plugin Recommendations

Using media queries for responsive CSS

<style>
  @media only screen and (max-width:600px) {
    .a-unique-class { ... }
  }
</style>

<div class="a-unique-class">
  ...
</div>

Example Plugin

You can view an example editor block plugin implementation here.

Reference

Accounts

Get current account

Code samples

# You can also use wget
curl -X GET https://api.kit.com/v4/account \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN_HERE'


const headers = {
  'Accept':'application/json',
  'Authorization':'Bearer YOUR_ACCESS_TOKEN_HERE'
};

fetch('https://api.kit.com/v4/account',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

result = RestClient.get 'https://api.kit.com/v4/account',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

r = requests.get('https://api.kit.com/v4/account', headers = headers)

print(r.json())

GET /v4/account

Parameters

AuthorizationsOAuth2, API Key

Header Parameters

Authorizationrequired
string
Example: Bearer YOUR_ACCESS_TOKEN_HERE

Responses

Example responses

200 Response

{
  "user": {
    "email": "test@convertkit.dev"
  },
  "account": {
    "name": "Kit Greetings",
    "plan_type": "creator",
    "primary_email_address": "test@convertkit.dev",
    "created_at": "2023-02-17T11:43:55Z",
    "id": 26
  }
}

401 Response

{
  "errors": [
    "The access token is invalid"
  ]
}

200

Returns current account and user info

Response Schema: application/json

userrequired
object
» emailrequired
string
accountrequired
object
» namerequired
string
» plan_typerequired
string
» primary_email_addressrequired
string
» created_at
string
» id
integer

401

Returns a 401 if the token and/or account cannot be authenticated

Response Schema: application/json

errorsrequired
[string]

List colors

Code samples

# You can also use wget
curl -X GET https://api.kit.com/v4/account/colors \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN_HERE'


const headers = {
  'Accept':'application/json',
  'Authorization':'Bearer YOUR_ACCESS_TOKEN_HERE'
};

fetch('https://api.kit.com/v4/account/colors',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

result = RestClient.get 'https://api.kit.com/v4/account/colors',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

r = requests.get('https://api.kit.com/v4/account/colors', headers = headers)

print(r.json())

GET /v4/account/colors

Parameters

AuthorizationsOAuth2, API Key

Header Parameters

Authorizationrequired
string
Example: Bearer YOUR_ACCESS_TOKEN_HERE

Responses

Example responses

200 Response

{
  "colors": [
    "#008000",
    "#FF0000"
  ]
}

401 Response

{
  "errors": [
    "The access token is invalid"
  ]
}

200

Returns list of colors for the current account

Response Schema: application/json

colorsrequired
[string]

401

Returns a 401 if the token and/or account cannot be authenticated

Response Schema: application/json

errorsrequired
[string]

Update colors

Code samples

# You can also use wget
curl -X PUT https://api.kit.com/v4/account/colors \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN_HERE'

const inputBody = '{
  "colors": [
    "#000000",
    "#ffffff"
  ]
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'Bearer YOUR_ACCESS_TOKEN_HERE'
};

fetch('https://api.kit.com/v4/account/colors',
{
  method: 'PUT',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

result = RestClient.put 'https://api.kit.com/v4/account/colors',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

r = requests.put('https://api.kit.com/v4/account/colors', headers = headers)

print(r.json())

PUT /v4/account/colors

Body parameter

{
  "colors": [
    "#000000",
    "#ffffff"
  ]
}

Parameters

AuthorizationsOAuth2, API Key

Header Parameters

Authorizationrequired
string
Example: Bearer YOUR_ACCESS_TOKEN_HERE

Request Body Schemaapplication/json

colorsrequired
[string]
An array of up to 5 color hex codes

Responses

Example responses

200 Response

{
  "colors": [
    "#000000",
    "#ffffff"
  ]
}

401 Response

{
  "errors": [
    "The access token is invalid"
  ]
}

422 Response

{
  "errors": [
    "Colors #123_not_a_code is not a valid hex color code."
  ]
}

200

Updates and returns list of colors for the current account

Response Schema: application/json

colorsrequired
[string]

401

Returns a 401 if the token and/or account cannot be authenticated

Response Schema: application/json

errorsrequired
[string]

422

Returns a 422 with an error message when invalid color code is provided

Response Schema: application/json

errorsrequired
[string]

Get Creator Profile

Code samples

# You can also use wget
curl -X GET https://api.kit.com/v4/account/creator_profile \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN_HERE'


const headers = {
  'Accept':'application/json',
  'Authorization':'Bearer YOUR_ACCESS_TOKEN_HERE'
};

fetch('https://api.kit.com/v4/account/creator_profile',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

result = RestClient.get 'https://api.kit.com/v4/account/creator_profile',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

r = requests.get('https://api.kit.com/v4/account/creator_profile', headers = headers)

print(r.json())

GET /v4/account/creator_profile

Parameters

AuthorizationsOAuth2, API Key

Header Parameters

Authorizationrequired
string
Example: Bearer YOUR_ACCESS_TOKEN_HERE

Responses

Example responses

200 Response

{
  "profile": {
    "name": "A Creator's Journey",
    "byline": "A Creator",
    "bio": "Follow my Journey as a Creator",
    "image_url": "https://convertkit.dev/image.jpg?fit=crop&h=320&w=320",
    "profile_url": "https://kit-greetings.ck.page/profile"
  }
}

401 Response

{
  "errors": [
    "The access token is invalid"
  ]
}

404 Response

{
  "errors": [
    "Not Found"
  ]
}

200

Returns Creator Profile details

Response Schema: application/json

profilerequired
object
» namerequired
string
» bylinerequired
string
» biorequired
string
» image_urlrequired
string
» profile_urlrequired
string

401

Returns a 401 if the token and/or account cannot be authenticated

Response Schema: application/json

errorsrequired
[string]

404

Returns a 404 if the creator profile doesn't exist

Response Schema: application/json

errorsrequired
[string]

Get email stats

Code samples

# You can also use wget
curl -X GET https://api.kit.com/v4/account/email_stats \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN_HERE'


const headers = {
  'Accept':'application/json',
  'Authorization':'Bearer YOUR_ACCESS_TOKEN_HERE'
};

fetch('https://api.kit.com/v4/account/email_stats',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

result = RestClient.get 'https://api.kit.com/v4/account/email_stats',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

r = requests.get('https://api.kit.com/v4/account/email_stats', headers = headers)

print(r.json())

GET /v4/account/email_stats

Parameters

AuthorizationsOAuth2, API Key

Header Parameters

Authorizationrequired
string
Example: Bearer YOUR_ACCESS_TOKEN_HERE

Responses

Example responses

200 Response

{
  "stats": {
    "sent": 6,
    "clicked": 3,
    "opened": 6,
    "email_stats_mode": "last_90",
    "open_tracking_enabled": true,
    "click_tracking_enabled": true,
    "starting": "2022-11-19T11:43:55Z",
    "ending": "2023-02-17T11:43:55Z"
  }
}

401 Response

{
  "errors": [
    "The access token is invalid"
  ]
}

200

Returns your email stats for the last 90 days

Response Schema: application/json

statsrequired
object
» sentrequired
integer
» clickedrequired
integer
» openedrequired
integer
» email_stats_moderequired
string
» open_tracking_enabledrequired
boolean
» click_tracking_enabledrequired
boolean
» startingrequired
string
» endingrequired
string

401

Returns a 401 if the token and/or account cannot be authenticated

Response Schema: application/json

errorsrequired
[string]

Get growth stats

Code samples

# You can also use wget
curl -X GET https://api.kit.com/v4/account/growth_stats \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN_HERE'


const headers = {
  'Accept':'application/json',
  'Authorization':'Bearer YOUR_ACCESS_TOKEN_HERE'
};

fetch('https://api.kit.com/v4/account/growth_stats',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

result = RestClient.get 'https://api.kit.com/v4/account/growth_stats',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

r = requests.get('https://api.kit.com/v4/account/growth_stats', headers = headers)

print(r.json())

GET /v4/account/growth_stats

Get growth stats for a specific time period. Defaults to last 90 days.

NOTE: We return your stats in your sending time zone. This endpoint does not return timestamps in UTC.

Parameters

AuthorizationsOAuth2, API Key

Query Parameters

ending
string
Example: ending=02/09/2023
Get stats for time period ending on this date (format yyyy-mm-dd). Defaults to today.
starting
string
Example: starting=02/10/2023
Get stats for time period beginning on this date (format yyyy-mm-dd). Defaults to 90 days ago.

Header Parameters

Authorizationrequired
string
Example: Bearer YOUR_ACCESS_TOKEN_HERE

Responses

Example responses

200 Response

{
  "stats": {
    "cancellations": 0,
    "net_new_subscribers": 3,
    "new_subscribers": 3,
    "subscribers": 3,
    "starting": "2023-02-10T00:00:00-05:00",
    "ending": "2023-02-24T23:59:59-05:00"
  }
}

401 Response

{
  "errors": [
    "The access token is invalid"
  ]
}

422 Response

{
  "errors": [
    "Starting date is incorrectly formatted. Use YYYY-MM-DD.",
    "Ending date is incorrectly formatted. Use YYYY-MM-DD.",
    "Starting date must be before the ending date."
  ]
}

200

Returns your growth stats for the provided starting and ending dates

Response Schema: application/json

statsrequired
object
» cancellationsrequired
integer
» net_new_subscribersrequired
integer
» new_subscribersrequired
integer
» subscribersrequired
integer
» startingrequired
string
» endingrequired
string

401

Returns a 401 if the token and/or account cannot be authenticated

Response Schema: application/json

errorsrequired
[string]

422

Returns a 422 with an error message if the starting or ending params are misformatted or the range is invalid

Response Schema: application/json

errorsrequired
[string]

Broadcasts

List broadcasts

Code samples

# You can also use wget
curl -X GET https://api.kit.com/v4/broadcasts \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN_HERE'


const headers = {
  'Accept':'application/json',
  'Authorization':'Bearer YOUR_ACCESS_TOKEN_HERE'
};

fetch('https://api.kit.com/v4/broadcasts',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

result = RestClient.get 'https://api.kit.com/v4/broadcasts',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

r = requests.get('https://api.kit.com/v4/broadcasts', headers = headers)

print(r.json())

GET /v4/broadcasts

Parameters

AuthorizationsOAuth2, API Key

Query Parameters

after
any
Example: after=WzFd
To fetch next page of results, use ?after=<end_cursor>
before
any
Example: before=WzNd
To fetch previous page of results, use ?before=<start_cursor>
include_total_count
string
Example: include_total_count=false
To include the total count of records in the response, use true. For large collections, expect a slightly slower response.
per_page
any
Example: per_page=10
Number of results per page. Default 500, maximum 1000.

Header Parameters

Authorizationrequired
string
Example: Bearer YOUR_ACCESS_TOKEN_HERE

Responses

Example responses

200 Response

{
  "broadcasts": [
    {
      "id": 3,
      "publication_id": 3,
      "created_at": "2023-02-17T11:43:55Z",
      "subject": "Productivity tricks",
      "preview_text": null,
      "description": null,
      "content": null,
      "public": false,
      "published_at": null,
      "send_at": null,
      "thumbnail_alt": null,
      "thumbnail_url": null,
      "email_address": null,
      "email_template": {
        "id": 6,
        "name": "Text Only"
      },
      "subscriber_filter": [
        {
          "all": [
            {
              "type": "all_subscribers"
            }
          ]
        }
      ]
    },
    {
      "id": 2,
      "publication_id": 2,
      "created_at": "2023-02-17T11:43:55Z",
      "subject": "5 tips for a less stressful work week",
      "preview_text": null,
      "description": null,
      "content": null,
      "public": false,
      "published_at": null,
      "send_at": "2023-02-17T11:53:55Z",
      "thumbnail_alt": null,
      "thumbnail_url": null,
      "email_address": null,
      "email_template": {
        "id": 6,
        "name": "Text Only"
      },
      "subscriber_filter": [
        {
          "all": [
            {
              "type": "all_subscribers"
            }
          ]
        }
      ]
    },
    {
      "id": 1,
      "publication_id": 1,
      "created_at": "2023-02-14T11:43:55Z",
      "subject": "You'll never guess...",
      "preview_text": null,
      "description": null,
      "content": null,
      "public": false,
      "published_at": "2023-02-17T11:43:55Z",
      "send_at": "2023-02-17T11:38:55Z",
      "thumbnail_alt": null,
      "thumbnail_url": null,
      "email_address": null,
      "email_template": {
        "id": 6,
        "name": "Text Only"
      },
      "subscriber_filter": [
        {
          "all": [
            {
              "type": "all_subscribers"
            }
          ]
        }
      ]
    }
  ],
  "pagination": {
    "has_previous_page": false,
    "has_next_page": false,
    "start_cursor": "WzNd",
    "end_cursor": "WzFd",
    "per_page": 500
  }
}

401 Response

{
  "errors": [
    "The access token is invalid"
  ]
}

200

Returns a paginated list of all broadcasts for your account (including draft, scheduled, and already sent)

Response Schema: application/json

broadcastsrequired
[object]
» idrequired
integer
» created_atrequired
string
» subjectrequired
string
» descriptionrequired
any
» contentrequired
any
» publicrequired
boolean
» published_atrequired
any
» send_atrequired
any
» thumbnail_altrequired
any
» thumbnail_urlrequired
any
» email_addressrequired
any
» preview_text
any
» email_templaterequired
object
»» idrequired
integer
»» namerequired
string
» subscriber_filterrequired
[object]
»» allrequired
[object]
»»» typerequired
string
»»» ids
[integer]
»» any
[object]
»»» typerequired
string
»»» idsrequired
[integer]
»» none
[object]
»»» typerequired
string
»»» idsrequired
[integer]
» publication_id
integer
paginationrequired
object
» has_previous_pagerequired
boolean
» has_next_pagerequired
boolean
» start_cursorrequired
string¦null
» end_cursorrequired
string¦null
» per_pagerequired
integer

401

Returns a 401 if the token and/or account cannot be authenticated

Response Schema: application/json

errorsrequired
[string]

Create a broadcast

Code samples

# You can also use wget
curl -X POST https://api.kit.com/v4/broadcasts \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN_HERE'

const inputBody = '{
  "email_template_id": 2,
  "email_address": null,
  "content": "<p>Let me introduce myself</p>",
  "description": "Intro email",
  "public": true,
  "published_at": "2023-02-17T11:43:55+00:00",
  "send_at": null,
  "thumbnail_alt": null,
  "thumbnail_url": null,
  "preview_text": "Pleased to meet you!",
  "subject": "Hello!",
  "subscriber_filter": [
    {
      "all": [
        {
          "type": "segment",
          "ids": [
            16
          ]
        }
      ],
      "any": null,
      "none": null
    }
  ]
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'Bearer YOUR_ACCESS_TOKEN_HERE'
};

fetch('https://api.kit.com/v4/broadcasts',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

result = RestClient.post 'https://api.kit.com/v4/broadcasts',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

r = requests.post('https://api.kit.com/v4/broadcasts', headers = headers)

print(r.json())

POST /v4/broadcasts

Draft or schedule to send a broadcast to all or a subset of your subscribers.

To save a draft, set send_at to null.

To publish to the web, set public to true.

To schedule the broadcast for sending, provide a send_at timestamp. Scheduled broadcasts should contain a subject and your content, at a minimum.

We currently support targeting your subscribers based on segment or tag ids.

Body parameter

{
  "email_template_id": 2,
  "email_address": null,
  "content": "<p>Let me introduce myself</p>",
  "description": "Intro email",
  "public": true,
  "published_at": "2023-02-17T11:43:55+00:00",
  "send_at": null,
  "thumbnail_alt": null,
  "thumbnail_url": null,
  "preview_text": "Pleased to meet you!",
  "subject": "Hello!",
  "subscriber_filter": [
    {
      "all": [
        {
          "type": "segment",
          "ids": [
            16
          ]
        }
      ],
      "any": null,
      "none": null
    }
  ]
}

Parameters

AuthorizationsOAuth2, API Key

Header Parameters

Authorizationrequired
string
Example: Bearer YOUR_ACCESS_TOKEN_HERE

Request Body Schemaapplication/json

email_template_idrequired
integer or null
Id of the email template to use. Uses the account's default template if not provided. 'Starting point' template is not supported.
email_addressrequired
string or null
The sending email address to use. Uses the account's sending email address if not provided.
contentrequired
string or null
The HTML content of the email.
descriptionrequired
string or null
publicrequired
boolean or null
true to publish this broadcast to the web. The broadcast will appear in a newsletter feed on your Creator Profile and Landing Pages.
published_atrequired
string or null
The published timestamp to display in ISO8601 format. If no timezone is provided, UTC is assumed.
send_atrequired
string or null
The scheduled send time for this broadcast in ISO8601 format. If no timezone is provided, UTC is assumed.
thumbnail_altrequired
string or null
thumbnail_urlrequired
string or null
preview_textrequired
string or null
subjectrequired
string or null
subscriber_filterrequired
[object] or null
Filters your subscribers. At this time, we only support using only one filter group type via the API (e.g. all, any, or none but no combinations). If nothing is provided, will default to all of your subscribers.
» allrequired
[object] or null
Filters your subscribers using a logical AND of all provided segment and tag ids, i.e. a subscriber would have to be part of all segments and tags provided
»» typerequired
string
segment or tag
»» idsrequired
[integer]
» anyrequired
[object] or null
Filters your subscribers using a logical OR of all provided segment and tag ids, i.e. a subscriber would have to be part of at least one of the segments or tags provided
»» typerequired
string
segment or tag
»» idsrequired
[string]
» nonerequired
[object] or null
Filters your subscribers using a logical NOT of all provided segment and tag ids, i.e. a subscriber would have to be in none of the segments or tags provided
»» typerequired
string
segment or tag
»» idsrequired
[string]

Responses

Example responses

201 Response

{
  "broadcast": {
    "id": 25,
    "created_at": "2023-02-17T11:43:55Z",
    "subject": "Hello!",
    "preview_text": "Pleased to meet you!",
    "description": "Intro email",
    "content": "<p>Let me introduce myself</p>",
    "public": true,
    "published_at": "2023-02-17T11:43:55Z",
    "send_at": null,
    "thumbnail_alt": null,
    "thumbnail_url": null,
    "email_address": "greetings@convertkit.dev",
    "email_template": {
      "id": 2,
      "name": "Classic"
    },
    "subscriber_filter": [
      {
        "all": [
          {
            "type": "segment",
            "ids": [
              16
            ]
          }
        ]
      }
    ],
    "publication_id": 25
  }
}

401 Response

{
  "errors": [
    "The access token is invalid"
  ]
}

403 Response

{
  "errors": [
    "You do not have sufficient permissions to access this resource. Please contact support."
  ]
}

422 Response

{
  "errors": [
    "Email template not found",
    "Only a single filter group is supported. Use one of `all`, `any`, or `none`."
  ]
}

201

Creates a new broadcast

Response Schema: application/json

broadcastrequired
object
» idrequired
integer
» created_atrequired
string
» subjectrequired
string
» preview_textrequired
string
» descriptionrequired
string
» contentrequired
string
» publicrequired
boolean
» published_atrequired
string
» send_atrequired
string¦null
» thumbnail_altrequired
any
» thumbnail_urlrequired
any
» email_addressrequired
string
» email_templaterequired
object
»» idrequired
integer
»» namerequired
string
» subscriber_filterrequired
[object]
»» allrequired
[object]
»»» typerequired
string
»»» idsrequired
[integer]
»» any
[object]
»»» typerequired
string
»»» idsrequired
[integer]
»» none
[object]
»»» typerequired
string
»»» idsrequired
[integer]
» publication_id
integer

401

Returns a 401 if the token and/or account cannot be authenticated

Response Schema: application/json

errorsrequired
[string]

403

Returns a 403 with an error message if the current account is unauthorized to create a broadcast

Response Schema: application/json

errorsrequired
[string]

422

Returns a 422 with an error message when one or more of the parameters were invalid

Response Schema: application/json

errorsrequired
[string]

Delete a broadcast

Code samples

# You can also use wget
curl -X DELETE https://api.kit.com/v4/broadcasts/{id} \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -H 'Accept: ' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN_HERE'

const inputBody = '{}';
const headers = {
  'Content-Type':'application/x-www-form-urlencoded',
  'Accept':'',
  'Authorization':'Bearer YOUR_ACCESS_TOKEN_HERE'
};

fetch('https://api.kit.com/v4/broadcasts/{id}',
{
  method: 'DELETE',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/x-www-form-urlencoded',
  'Accept' => '',
  'Authorization' => 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

result = RestClient.delete 'https://api.kit.com/v4/broadcasts/{id}',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/x-www-form-urlencoded',
  'Accept': '',
  'Authorization': 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

r = requests.delete('https://api.kit.com/v4/broadcasts/{id}', headers = headers)

print(r.json())

DELETE /v4/broadcasts/{id}

Body parameter

{}

Parameters

AuthorizationsOAuth2, API Key

Path Parameters

idrequired
integer
Example: 80

Header Parameters

Authorizationrequired
string
Example: Bearer YOUR_ACCESS_TOKEN_HERE

Responses

Example responses

204 Response

401 Response

{
  "errors": [
    "The access token is invalid"
  ]
}

403 Response

{
  "errors": [
    "You do not have sufficient permissions to access this resource. Please contact support."
  ]
}

404 Response

{
  "errors": [
    "Not Found"
  ]
}

422 Response

{
  "errors": [
    "Broadcast is already sending."
  ]
}

204

Deletes the broadcast

401

Returns a 401 if the token and/or account cannot be authenticated

Response Schema: application/json

errorsrequired
[string]

403

Returns a 403 with an error message if the current account is unauthorized to update a broadcast

Response Schema: application/json

errorsrequired
[string]

404

Returns a 404 when the provided id does not exist

Response Schema: application/json

errorsrequired
[string]

422

Returns a 422 with an error message if the broadcast has already started sending or already sent

Response Schema: application/json

errorsrequired
[string]

Get a broadcast

Code samples

# You can also use wget
curl -X GET https://api.kit.com/v4/broadcasts/{id} \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN_HERE'


const headers = {
  'Accept':'application/json',
  'Authorization':'Bearer YOUR_ACCESS_TOKEN_HERE'
};

fetch('https://api.kit.com/v4/broadcasts/{id}',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

result = RestClient.get 'https://api.kit.com/v4/broadcasts/{id}',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

r = requests.get('https://api.kit.com/v4/broadcasts/{id}', headers = headers)

print(r.json())

GET /v4/broadcasts/{id}

Parameters

AuthorizationsOAuth2, API Key

Path Parameters

idrequired
integer
Example: 20

Header Parameters

Authorizationrequired
string
Example: Bearer YOUR_ACCESS_TOKEN_HERE

Responses

Example responses

200 Response

{
  "broadcast": {
    "id": 19,
    "created_at": "2023-02-17T11:43:55Z",
    "subject": "You'll never guess...",
    "description": null,
    "content": null,
    "public": false,
    "published_at": null,
    "send_at": null,
    "thumbnail_alt": null,
    "thumbnail_url": null,
    "email_address": null,
    "preview_text": null,
    "email_template": {
      "id": 6,
      "name": "Text Only"
    },
    "subscriber_filter": [
      {
        "all": [
          {
            "type": "all_subscribers"
          }
        ]
      }
    ],
    "publication_id": 19
  }
}

401 Response

{
  "errors": [
    "The access token is invalid"
  ]
}

404 Response

{
  "errors": [
    "Not Found"
  ]
}

200

Returns the broadcast details

Response Schema: application/json

broadcastrequired
object
» idrequired
integer
» created_atrequired
string
» subjectrequired
string
» descriptionrequired
any
» contentrequired
any
» publicrequired
boolean
» published_atrequired
any
» send_atrequired
any
» thumbnail_altrequired
any
» thumbnail_urlrequired
any
» email_addressrequired
any
» preview_text
any
» email_templaterequired
object
»» idrequired
integer
»» namerequired
string
» subscriber_filterrequired
[object]
»» allrequired
[object]
»»» typerequired
string
»»» ids
[integer]
»» any
[object]
»»» typerequired
string
»»» idsrequired
[integer]
»» none
[object]
»»» typerequired
string
»»» idsrequired
[integer]
» publication_id
integer

401

Returns a 401 if the token and/or account cannot be authenticated

Response Schema: application/json

errorsrequired
[string]

404

Returns a 404 when the provided id does not exist

Response Schema: application/json

errorsrequired
[string]

Update a broadcast

Code samples

# You can also use wget
curl -X PUT https://api.kit.com/v4/broadcasts/{id} \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN_HERE'

const inputBody = '{
  "email_template_id": 2,
  "email_address": null,
  "content": "<p>Let me introduce myself</p>",
  "description": "Intro email",
  "public": true,
  "published_at": "2023-02-17T11:43:55+00:00",
  "send_at": "2023-02-17T11:43:55+00:00",
  "thumbnail_alt": null,
  "thumbnail_url": null,
  "preview_text": "Pleased to meet you!",
  "subject": "Hello!",
  "subscriber_filter": [
    {
      "all": [
        {
          "type": "segment",
          "ids": [
            41
          ]
        }
      ],
      "any": null,
      "none": null
    }
  ]
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'Bearer YOUR_ACCESS_TOKEN_HERE'
};

fetch('https://api.kit.com/v4/broadcasts/{id}',
{
  method: 'PUT',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

result = RestClient.put 'https://api.kit.com/v4/broadcasts/{id}',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

r = requests.put('https://api.kit.com/v4/broadcasts/{id}', headers = headers)

print(r.json())

PUT /v4/broadcasts/{id}

Update an existing broadcast. Continue to draft or schedule to send a broadcast to all or a subset of your subscribers.

To save a draft, set public to false.

To schedule the broadcast for sending, set public to true and provide send_at. Scheduled broadcasts should contain a subject and your content, at a minimum.

We currently support targeting your subscribers based on segment or tag ids.

Body parameter

{
  "email_template_id": 2,
  "email_address": null,
  "content": "<p>Let me introduce myself</p>",
  "description": "Intro email",
  "public": true,
  "published_at": "2023-02-17T11:43:55+00:00",
  "send_at": "2023-02-17T11:43:55+00:00",
  "thumbnail_alt": null,
  "thumbnail_url": null,
  "preview_text": "Pleased to meet you!",
  "subject": "Hello!",
  "subscriber_filter": [
    {
      "all": [
        {
          "type": "segment",
          "ids": [
            41
          ]
        }
      ],
      "any": null,
      "none": null
    }
  ]
}

Parameters

AuthorizationsOAuth2, API Key

Path Parameters

idrequired
integer
Example: 56

Header Parameters

Authorizationrequired
string
Example: Bearer YOUR_ACCESS_TOKEN_HERE

Request Body Schemaapplication/json

email_template_idrequired
integer or null
Id of the email template to use. Uses the account's default template if not provided.
email_addressrequired
string or null
The sending email address to use. Uses the account's sending email address if not provided.
contentrequired
string or null
The HTML content of the email.
descriptionrequired
string or null
publicrequired
boolean or null
true to publish this broadcast. false to save a draft.
published_atrequired
string or null
The published timestamp to display in ISO8601 format. If no timezone is provided, UTC is assumed.
send_atrequired
string or null
The scheduled send time for this broadcast in ISO8601 format. If no timezone is provided, UTC is assumed.
thumbnail_altrequired
string or null
thumbnail_urlrequired
string or null
preview_textrequired
string or null
subjectrequired
string or null
subscriber_filterrequired
[object] or null
Filters your subscribers. At this time, we only support using only one filter group type via the API (e.g. all, any, or none but no combinations). If nothing is provided, will default to all of your subscribers.
» allrequired
[object] or null
Filters your subscribers using a logical AND of all provided segment and tag ids, i.e. a subscriber would have to be part of all segments and tags provided
»» typerequired
string
segment or tag
»» idsrequired
[integer]
» anyrequired
[object] or null
Filters your subscribers using a logical OR of all provided segment and tag ids, i.e. a subscriber would have to be part of at least one of the segments or tags provided
»» typerequired
string
segment or tag
»» idsrequired
[string]
» nonerequired
[object] or null
Filters your subscribers using a logical NOT of all provided segment and tag ids, i.e. a subscriber would have to be in none of the segments or tags provided
»» typerequired
string
segment or tag
»» idsrequired
[string]

Responses

Example responses

200 Response

{
  "broadcast": {
    "id": 47,
    "created_at": "2023-02-17T11:43:55Z",
    "subject": "Hello!",
    "preview_text": "Pleased to meet you!",
    "description": "Intro email",
    "content": "<p>Let me introduce myself</p>",
    "public": true,
    "published_at": "2023-02-17T11:43:55Z",
    "send_at": "2023-02-17T11:43:55Z",
    "thumbnail_alt": null,
    "thumbnail_url": null,
    "email_address": "greetings@convertkit.dev",
    "email_template": {
      "id": 2,
      "name": "Classic"
    },
    "subscriber_filter": [
      {
        "all": [
          {
            "type": "segment",
            "ids": [
              41
            ]
          }
        ]
      }
    ],
    "publication_id": 47
  }
}

401 Response

{
  "errors": [
    "The access token is invalid"
  ]
}

403 Response

{
  "errors": [
    "You do not have sufficient permissions to access this resource. Please contact support."
  ]
}

404 Response

{
  "errors": [
    "Not Found"
  ]
}

422 Response

{
  "errors": [
    "Email template not found",
    "Only a single filter group is supported. Use one of `all`, `any`, or `none`."
  ]
}

200

Updates the broadcast and returns its details

Response Schema: application/json

broadcastrequired
object
» idrequired
integer
» created_atrequired
string
» subjectrequired
string
» preview_textrequired
string
» descriptionrequired
string
» contentrequired
string
» publicrequired
boolean
» published_atrequired
string
» send_atrequired
string
» thumbnail_altrequired
any
» thumbnail_urlrequired
any
» email_addressrequired
string
» email_templaterequired
object
»» idrequired
integer
»» namerequired
string
» subscriber_filterrequired
[object]
»» allrequired
[object]
»»» typerequired
string
»»» idsrequired
[integer]
» publication_id
integer

401

Returns a 401 if the token and/or account cannot be authenticated

Response Schema: application/json

errorsrequired
[string]

403

Returns a 403 with an error message if the current account is unauthorized to create a broadcast

Response Schema: application/json

errorsrequired
[string]

404

Returns a 404 when the provided id does not exist

Response Schema: application/json

errorsrequired
[string]

422

Returns a 422 with an error message when one or more of the parameters are invalid or the campaign has already started sending

Response Schema: application/json

errorsrequired
[string]

Get stats

Code samples

# You can also use wget
curl -X GET https://api.kit.com/v4/broadcasts/{id}/stats \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN_HERE'


const headers = {
  'Accept':'application/json',
  'Authorization':'Bearer YOUR_ACCESS_TOKEN_HERE'
};

fetch('https://api.kit.com/v4/broadcasts/{id}/stats',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

result = RestClient.get 'https://api.kit.com/v4/broadcasts/{id}/stats',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

r = requests.get('https://api.kit.com/v4/broadcasts/{id}/stats', headers = headers)

print(r.json())

GET /v4/broadcasts/{id}/stats

Parameters

AuthorizationsOAuth2, API Key

Path Parameters

idrequired
integer
Example: 97

Header Parameters

Authorizationrequired
string
Example: Bearer YOUR_ACCESS_TOKEN_HERE

Responses

Example responses

200 Response

{
  "broadcast": {
    "id": 96,
    "stats": {
      "recipients": 0,
      "open_rate": 0,
      "click_rate": 0,
      "unsubscribes": 0,
      "total_clicks": 0,
      "show_total_clicks": false,
      "status": "draft",
      "progress": 0,
      "open_tracking_disabled": false,
      "click_tracking_disabled": false
    }
  }
}

401 Response

{
  "errors": [
    "The access token is invalid"
  ]
}

404 Response

{
  "errors": [
    "Not Found"
  ]
}

200

Returns stats for a broadcast

Response Schema: application/json

broadcastrequired
object
» idrequired
integer
» statsrequired
object
»» recipientsrequired
integer
»» open_raterequired
number(float)
»» click_raterequired
number(float)
»» unsubscribesrequired
integer
»» total_clicksrequired
integer
»» show_total_clicksrequired
boolean
»» statusrequired
string
»» progressrequired
number(float)
»» open_tracking_disabledrequired
boolean
»» click_tracking_disabledrequired
boolean

401

Returns a 401 if the token and/or account cannot be authenticated

Response Schema: application/json

errorsrequired
[string]

404

Returns a 404 when the provided id does not exist

Response Schema: application/json

errorsrequired
[string]

Custom Fields

Bulk create custom fields

Code samples

# You can also use wget
curl -X POST https://api.kit.com/v4/bulk/custom_fields \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN_HERE'

const inputBody = '{
  "custom_fields": [
    {
      "label": "Test Custom Field 0"
    },
    {
      "label": "Test Custom Field 1"
    },
    {
      "label": "Test Custom Field 2"
    },
    {
      "label": "Test Custom Field 3"
    }
  ],
  "callback_url": null
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'Bearer YOUR_ACCESS_TOKEN_HERE'
};

fetch('https://api.kit.com/v4/bulk/custom_fields',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

result = RestClient.post 'https://api.kit.com/v4/bulk/custom_fields',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

r = requests.post('https://api.kit.com/v4/bulk/custom_fields', headers = headers)

print(r.json())

POST /v4/bulk/custom_fields

See "Bulk & async processing" for more information.

Body parameter

{
  "custom_fields": [
    {
      "label": "Test Custom Field 0"
    },
    {
      "label": "Test Custom Field 1"
    },
    {
      "label": "Test Custom Field 2"
    },
    {
      "label": "Test Custom Field 3"
    }
  ],
  "callback_url": null
}

Parameters

AuthorizationsOAuth2

Header Parameters

Authorizationrequired
string
Example: Bearer YOUR_ACCESS_TOKEN_HERE

Request Body Schemaapplication/json

custom_fieldsrequired
[object]
» labelrequired
string
callback_url
any

Responses

Example responses

200 Response

{
  "custom_fields": [
    {
      "id": 80,
      "label": "Interests",
      "key": "interests",
      "name": "ck_field_80_interests",
      "created_at": "2023-02-17T11:43:55Z"
    },
    {
      "id": 79,
      "label": "Last name",
      "key": "last_name",
      "name": "ck_field_79_last_name",
      "created_at": "2023-02-17T11:43:55Z"
    }
  ],
  "failures": [
    {
      "custom_field": {
        "id": 78,
        "label": "Existing Custom Field",
        "key": "existing_custom_field",
        "name": "ck_field_78_existing_custom_field",
        "created_at": "2023-02-17T11:43:55Z"
      },
      "errors": [
        "Label has already been taken"
      ]
    }
  ]
}

202 Response

{}

401 Response

{
  "errors": [
    "The access token is invalid"
  ]
}

413 Response

{
  "errors": [
    "This request exceeds your queued bulk requests limit. Please wait while we process your existing requests and try again later."
  ]
}

422 Response

{
  "errors": [
    "No custom fields included for processing"
  ]
}

200

Creates the custom_fields synchronously when 100 or less custom fields are requested

Response Schema: application/json

custom_fieldsrequired
[object]
» idrequired
integer
» labelrequired
string
» keyrequired
string
» namerequired
string
» created_atrequired
string
failuresrequired
[object]
» custom_fieldrequired
object
»» idrequired
integer
»» labelrequired
string
»» keyrequired
string
»» namerequired
string
»» created_atrequired
string
» errorsrequired
[string]

202

Creates or updates custom_fields asynchronously when more than 100 custom fields are requested

Response Schema: application/json

401

Returns a 401 if the token and/or account cannot be authenticated

Response Schema: application/json

errorsrequired
[string]

413

Returns a 413 when the size of the request would exceed the account's data limit for enqueued bulk requests

Response Schema: application/json

errorsrequired
[string]

422

Returns a 422 when custom_fields is empty or not an array

Response Schema: application/json

errorsrequired
[string]

List custom fields

Code samples

# You can also use wget
curl -X GET https://api.kit.com/v4/custom_fields \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN_HERE'


const headers = {
  'Accept':'application/json',
  'Authorization':'Bearer YOUR_ACCESS_TOKEN_HERE'
};

fetch('https://api.kit.com/v4/custom_fields',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

result = RestClient.get 'https://api.kit.com/v4/custom_fields',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

r = requests.get('https://api.kit.com/v4/custom_fields', headers = headers)

print(r.json())

GET /v4/custom_fields

A custom field allows you to collect subscriber information beyond the standard fields of first name and email address. An example would be a custom field called last name so you can get the full names of your subscribers.

You create a custom field, and then you're able to use that in your forms or emails.

Parameters

AuthorizationsOAuth2, API Key

Query Parameters

after
any
Example: after=WzFd
To fetch next page of results, use ?after=<end_cursor>
before
any
Example: before=WzNd
To fetch previous page of results, use ?before=<start_cursor>
include_total_count
string
Example: include_total_count=false
To include the total count of records in the response, use true. For large collections, expect a slightly slower response.
per_page
any
Example: per_page=10
Number of results per page. Default 500, maximum 1000.

Header Parameters

Authorizationrequired
string
Example: Bearer YOUR_ACCESS_TOKEN_HERE

Responses

Example responses

200 Response

{
  "custom_fields": [
    {
      "id": 1,
      "name": "ck_field_1_last_name",
      "key": "last_name",
      "label": "Last name"
    }
  ],
  "pagination": {
    "has_previous_page": false,
    "has_next_page": false,
    "start_cursor": "WzFd",
    "end_cursor": "WzFd",
    "per_page": 500
  }
}

401 Response

{
  "errors": [
    "The access token is invalid"
  ]
}

200

Returns a paginated list of all custom fields for your account

Response Schema: application/json

custom_fieldsrequired
[object]
» idrequired
integer
» namerequired
string
» keyrequired
string
» labelrequired
string
paginationrequired
object
» has_previous_pagerequired
boolean
» has_next_pagerequired
boolean
» start_cursorrequired
string¦null
» end_cursorrequired
string¦null
» per_pagerequired
integer

401

Returns a 401 if the token and/or account cannot be authenticated

Response Schema: application/json

errorsrequired
[string]

Create a custom field

Code samples

# You can also use wget
curl -X POST https://api.kit.com/v4/custom_fields \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN_HERE'

const inputBody = '{
  "label": "Interests"
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'Bearer YOUR_ACCESS_TOKEN_HERE'
};

fetch('https://api.kit.com/v4/custom_fields',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

result = RestClient.post 'https://api.kit.com/v4/custom_fields',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

r = requests.post('https://api.kit.com/v4/custom_fields', headers = headers)

print(r.json())

POST /v4/custom_fields

Create a custom field for your account. The label field must be unique to your account. Whitespace will be removed from the beginning and the end of your label.

Additionally, a key field and a name field will be generated for you. The key is an ASCII-only, lowercased, underscored representation of your label. This key must be unique to your account. Keys are used in personalization tags in sequences and broadcasts. Names are unique identifiers for use in the HTML of custom forms. They are made up of a combination of ID and the key of the custom field prefixed with "ck_field".

Body parameter

{
  "label": "Interests"
}

Parameters

AuthorizationsOAuth2, API Key

Header Parameters

Authorizationrequired
string
Example: Bearer YOUR_ACCESS_TOKEN_HERE

Request Body Schemaapplication/json

labelrequired
string

Responses

Example responses

201 Response

{
  "custom_field": {
    "id": 6,
    "name": "ck_field_6_interests",
    "key": "interests",
    "label": "Interests"
  }
}

401 Response

{
  "errors": [
    "The access token is invalid"
  ]
}

422 Response

{
  "errors": [
    "Label can't be blank"
  ]
}

201

Creates a new custom field and returns its details

Response Schema: application/json

custom_fieldrequired
object
» idrequired
integer
» namerequired
string
» keyrequired
string
» labelrequired
string

401

Returns a 401 if the token and/or account cannot be authenticated

Response Schema: application/json

errorsrequired
[string]

422

Returns a 422 with an error message when the label is missing

Response Schema: application/json

errorsrequired
[string]

Delete custom field

Code samples

# You can also use wget
curl -X DELETE https://api.kit.com/v4/custom_fields/{id} \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -H 'Accept: ' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN_HERE'

const inputBody = '{}';
const headers = {
  'Content-Type':'application/x-www-form-urlencoded',
  'Accept':'',
  'Authorization':'Bearer YOUR_ACCESS_TOKEN_HERE'
};

fetch('https://api.kit.com/v4/custom_fields/{id}',
{
  method: 'DELETE',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/x-www-form-urlencoded',
  'Accept' => '',
  'Authorization' => 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

result = RestClient.delete 'https://api.kit.com/v4/custom_fields/{id}',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/x-www-form-urlencoded',
  'Accept': '',
  'Authorization': 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

r = requests.delete('https://api.kit.com/v4/custom_fields/{id}', headers = headers)

print(r.json())

DELETE /v4/custom_fields/{id}

This will remove all data in this field from your subscribers.

Body parameter

{}

Parameters

AuthorizationsOAuth2, API Key

Path Parameters

idrequired
integer
Example: 42

Header Parameters

Authorizationrequired
string
Example: Bearer YOUR_ACCESS_TOKEN_HERE

Responses

Example responses

204 Response

401 Response

{
  "errors": [
    "The access token is invalid"
  ]
}

404 Response

{
  "errors": [
    "Not Found"
  ]
}

422 Response

{
  "errors": [
    "Unable to destroy the custom field."
  ]
}

204

Deletes the custom field

401

Returns a 401 if the token and/or account cannot be authenticated

Response Schema: application/json

errorsrequired
[string]

404

Returns a 404 when the provided id does not exist

Response Schema: application/json

errorsrequired
[string]

422

Returns a 422 when the custom field cannot be deleted

Response Schema: application/json

errorsrequired
[string]

Update a custom field

Code samples

# You can also use wget
curl -X PUT https://api.kit.com/v4/custom_fields/{id} \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN_HERE'

const inputBody = '{
  "label": "Last name"
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'Bearer YOUR_ACCESS_TOKEN_HERE'
};

fetch('https://api.kit.com/v4/custom_fields/{id}',
{
  method: 'PUT',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

result = RestClient.put 'https://api.kit.com/v4/custom_fields/{id}',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

r = requests.put('https://api.kit.com/v4/custom_fields/{id}', headers = headers)

print(r.json())

PUT /v4/custom_fields/{id}

Updates a custom field label (see Create a custom field above for more information on labels). Note that the key will change but the name remains the same when the label is updated.

Warning: An update to a custom field will break all of the liquid personalization tags in emails that reference it - e.g. if you update a Zip_Code custom field to Post_Code, all liquid tags referencing {{ subscriber.Zip_Code }} would no longer work and need to be replaced with {{ subscriber.Post_Code }}.

Body parameter

{
  "label": "Last name"
}

Parameters

AuthorizationsOAuth2, API Key

Path Parameters

idrequired
integer
Example: 24

Header Parameters

Authorizationrequired
string
Example: Bearer YOUR_ACCESS_TOKEN_HERE

Request Body Schemaapplication/json

labelrequired
string

Responses

Example responses

200 Response

{
  "custom_field": {
    "id": 22,
    "name": "ck_field_22_last_name",
    "key": "last_name",
    "label": "Last name"
  }
}

401 Response

{
  "errors": [
    "The access token is invalid"
  ]
}

404 Response

{
  "errors": [
    "Not Found"
  ]
}

422 Response

{
  "errors": [
    "Label can't be blank"
  ]
}

200

Updates the custom field and returns its details

Response Schema: application/json

custom_fieldrequired
object
» idrequired
integer
» namerequired
string
» keyrequired
string
» labelrequired
string

401

Returns a 401 if the token and/or account cannot be authenticated

Response Schema: application/json

errorsrequired
[string]

404

Returns a 404 when the provided id does not exist

Response Schema: application/json

errorsrequired
[string]

422

Returns a 422 with an error mesage when one or more of the parameters are invalid

Response Schema: application/json

errorsrequired
[string]

Forms

Bulk add subscribers to forms

Code samples

# You can also use wget
curl -X POST https://api.kit.com/v4/bulk/forms/subscribers \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN_HERE'

const inputBody = '{
  "additions": [
    {
      "form_id": 0,
      "subscriber_id": 0
    },
    {
      "form_id": 1,
      "subscriber_id": 1
    },
    {
      "form_id": 2,
      "subscriber_id": 2
    },
    {
      "form_id": 3,
      "subscriber_id": 3
    }
  ],
  "callback_url": null
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'Bearer YOUR_ACCESS_TOKEN_HERE'
};

fetch('https://api.kit.com/v4/bulk/forms/subscribers',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

result = RestClient.post 'https://api.kit.com/v4/bulk/forms/subscribers',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

r = requests.post('https://api.kit.com/v4/bulk/forms/subscribers', headers = headers)

print(r.json())

POST /v4/bulk/forms/subscribers

Adding subscribers to double opt-in forms will trigger sending an Incentive Email. Subscribers already added to the specified form will not receive the Incentive Email again. For more information about double opt-in see "Double opt-in".

See "Bulk & async processing" for more information.

Body parameter

{
  "additions": [
    {
      "form_id": 0,
      "subscriber_id": 0
    },
    {
      "form_id": 1,
      "subscriber_id": 1
    },
    {
      "form_id": 2,
      "subscriber_id": 2
    },
    {
      "form_id": 3,
      "subscriber_id": 3
    }
  ],
  "callback_url": null
}

Parameters

AuthorizationsOAuth2

Header Parameters

Authorizationrequired
string
Example: Bearer YOUR_ACCESS_TOKEN_HERE

Request Body Schemaapplication/json

additionsrequired
[object]
» form_idrequired
integer
» subscriber_idrequired
integer
» referrer
string
callback_url
any

Responses

Example responses

200 Response

{
  "subscribers": [
    {
      "id": 307,
      "first_name": "Sub",
      "email_address": "sub@example.com",
      "created_at": "2023-02-17T11:43:55Z",
      "added_at": "2023-02-17T11:43:55Z",
      "referrer": "https://mywebsite.com/bfpromo/?utm_source=facebook&utm_medium=cpc&utm_campaign=black_friday&utm_term=car_owners&utm_content=get_10_off",
      "referrer_utm_parameters": {
        "source": "facebook",
        "medium": "cpc",
        "campaign": "black_friday",
        "term": "car_owners",
        "content": "get_10_off"
      }
    },
    {
      "id": 307,
      "first_name": "Sub",
      "email_address": "sub@example.com",
      "created_at": "2023-02-17T11:43:55Z",
      "added_at": "2023-02-17T11:43:55Z",
      "referrer": "https://mywebsite.com/bfpromo/?utm_source=facebook&utm_medium=cpc&utm_campaign=black_friday&utm_term=car_owners&utm_content=get_10_off",
      "referrer_utm_parameters": {
        "source": "facebook",
        "medium": "cpc",
        "campaign": "black_friday",
        "term": "car_owners",
        "content": "get_10_off"
      }
    }
  ],
  "failures": []
}

202 Response

{}

401 Response

{
  "errors": [
    "The access token is invalid"
  ]
}

413 Response

{
  "errors": [
    "This request exceeds your queued bulk requests limit. Please wait while we process your existing requests and try again later."
  ]
}

422 Response

{
  "errors": [
    "No additions included for processing"
  ]
}

200

Adds subscribers to forms synchronously when 100 or less form/subscribers are requested

Response Schema: application/json

subscribersrequired
[object]
» idrequired
integer
» first_namerequired
string
» email_addressrequired
string
» created_atrequired
string
» added_atrequired
string
» referrer_utm_parameters
object
»» sourcerequired
string
»» mediumrequired
string
»» campaignrequired
string
»» termrequired
string
»» contentrequired
string
» referrer
string
failuresrequired
[any]

202

Adds subscribers to forms asynchronously when more than 100 form/subscribers are requested

Response Schema: application/json

401

Returns a 401 if the token and/or account cannot be authenticated

Response Schema: application/json

errorsrequired
[string]

413

Returns a 413 when the size of the request would exceed the account's data limit for enqueued bulk requests

Response Schema: application/json

errorsrequired
[string]

422

Returns a 422 when additions is empty or not an array

Response Schema: application/json

errorsrequired
[string]

List forms

Code samples

# You can also use wget
curl -X GET https://api.kit.com/v4/forms \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN_HERE'


const headers = {
  'Accept':'application/json',
  'Authorization':'Bearer YOUR_ACCESS_TOKEN_HERE'
};

fetch('https://api.kit.com/v4/forms',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

result = RestClient.get 'https://api.kit.com/v4/forms',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

r = requests.get('https://api.kit.com/v4/forms', headers = headers)

print(r.json())

GET /v4/forms

Parameters

AuthorizationsOAuth2, API Key

Query Parameters

after
any
Example: after=WzFd
To fetch next page of results, use ?after=<end_cursor>
before
any
Example: before=WzNd
To fetch previous page of results, use ?before=<start_cursor>
include_total_count
string
Example: include_total_count=false
To include the total count of records in the response, use true. For large collections, expect a slightly slower response.
per_page
any
Example: per_page=10
Number of results per page. Default 500, maximum 1000.
status
any
Filter forms that have this status (active, archived, trashed, or all). Defaults to active.
type
any
Filter forms and landing pages by type. Use embed for embedded forms. Use hosted for landing pages.

Header Parameters

Authorizationrequired
string
Example: Bearer YOUR_ACCESS_TOKEN_HERE

Responses

Example responses

200 Response

{
  "forms": [
    {
      "id": 44,
      "name": "Sign up",
      "created_at": "2023-02-17T11:43:55Z",
      "type": "embed",
      "format": null,
      "embed_js": "https://kit-greetings.ck.page/f049e3d9ab/index.js",
      "embed_url": "https://kit-greetings.ck.page/f049e3d9ab",
      "archived": false,
      "uid": "f049e3d9ab"
    },
    {
      "id": 43,
      "name": "Lead gen",
      "created_at": "2023-02-17T11:43:55Z",
      "type": "hosted",
      "format": null,
      "embed_js": "https://kit-greetings.ck.page/ae7c1adaa1/index.js",
      "embed_url": "https://kit-greetings.ck.page/ae7c1adaa1",
      "archived": false,
      "uid": "ae7c1adaa1"
    }
  ],
  "pagination": {
    "has_previous_page": false,
    "has_next_page": false,
    "start_cursor": "WzQ0XQ==",
    "end_cursor": "WzQzXQ==",
    "per_page": 500
  }
}

401 Response

{
  "errors": [
    "The access token is invalid"
  ]
}

200

Returns a paginated list of all forms and landing pages (embedded and hosted) for your account (including active and archived)

Response Schema: application/json

formsrequired
[object]
» idrequired
integer
» namerequired
string
» created_atrequired
string
» typerequired
string
» formatrequired
any
» embed_jsrequired
string
» embed_urlrequired
string
» archivedrequired
boolean
» uidrequired
string
paginationrequired
object
» has_previous_pagerequired
boolean
» has_next_pagerequired
boolean
» start_cursorrequired
string¦null
» end_cursorrequired
string¦null
» per_pagerequired
integer

401

Returns a 401 if the token and/or account cannot be authenticated

Response Schema: application/json

errorsrequired
[string]

List subscribers for a form

Code samples

# You can also use wget
curl -X GET https://api.kit.com/v4/forms/{form_id}/subscribers \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN_HERE'


const headers = {
  'Accept':'application/json',
  'Authorization':'Bearer YOUR_ACCESS_TOKEN_HERE'
};

fetch('https://api.kit.com/v4/forms/{form_id}/subscribers',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

result = RestClient.get 'https://api.kit.com/v4/forms/{form_id}/subscribers',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

r = requests.get('https://api.kit.com/v4/forms/{form_id}/subscribers', headers = headers)

print(r.json())

GET /v4/forms/{form_id}/subscribers

Parameters

AuthorizationsOAuth2, API Key

Path Parameters

form_idrequired
integer
Example: 138

Query Parameters

added_after
any
Example: added_after=2023-02-14T11:43:55Z
Filter subscribers who have been added to the form after this date (format yyyy-mm-dd)
added_before
any
Example: added_before=2023-02-18T11:43:55Z
Filter subscribers who have been added to the form before this date (format yyyy-mm-dd)
after
any
before
any
created_after
any
Example: created_after=2023-01-17T11:43:55Z
Filter subscribers who have been created after this date (format yyyy-mm-dd)
created_before
any
Example: created_before=2023-02-18T11:43:55Z
Filter subscribers who have been created before this date (format yyyy-mm-dd)
include_total_count
string
Example: include_total_count=false
To include the total count of records in the response, use true. For large collections, expect a slightly slower response.
per_page
any
status
string
Example: status=all
Filter subscribers who have this status (active, inactive, bounced, complained, cancelled or all). Defaults to active.

Header Parameters

Authorizationrequired
string
Example: Bearer YOUR_ACCESS_TOKEN_HERE

Responses

Example responses

200 Response

{
  "subscribers": [
    {
      "id": 345,
      "first_name": null,
      "email_address": "subscriber139@convertkit.dev",
      "state": "active",
      "created_at": "2023-02-17T11:43:55Z",
      "added_at": "2023-02-17T11:43:55Z",
      "fields": {
        "category": "One"
      },
      "referrer": "https://mywebsite.com/bfpromo/?utm_source=facebook&utm_medium=cpc&utm_campaign=black_friday&utm_term=car_owners&utm_content=get_10_off",
      "referrer_utm_parameters": {
        "source": "facebook",
        "medium": "cpc",
        "campaign": "black_friday",
        "term": "car_owners",
        "content": "get_10_off"
      }
    },
    {
      "id": 344,
      "first_name": null,
      "email_address": "subscriber138@convertkit.dev",
      "state": "active",
      "created_at": "2023-02-17T11:43:55Z",
      "added_at": "2023-02-17T11:43:55Z",
      "fields": {
        "category": null
      },
      "referrer": "https://mywebsite.com/bfpromo/?utm_source=facebook&utm_medium=cpc&utm_campaign=black_friday&utm_term=car_owners&utm_content=get_10_off",
      "referrer_utm_parameters": {
        "source": "facebook",
        "medium": "cpc",
        "campaign": "black_friday",
        "term": "car_owners",
        "content": "get_10_off"
      }
    },
    {
      "id": 343,
      "first_name": null,
      "email_address": "subscriber137@convertkit.dev",
      "state": "active",
      "created_at": "2023-02-17T11:43:55Z",
      "added_at": "2023-02-17T11:43:55Z",
      "fields": {
        "category": null
      },
      "referrer": "https://mywebsite.com/bfpromo/?utm_source=facebook&utm_medium=cpc&utm_campaign=black_friday&utm_term=car_owners&utm_content=get_10_off",
      "referrer_utm_parameters": {
        "source": "facebook",
        "medium": "cpc",
        "campaign": "black_friday",
        "term": "car_owners",
        "content": "get_10_off"
      }
    }
  ],
  "pagination": {
    "has_previous_page": false,
    "has_next_page": false,
    "start_cursor": "WzM0NV0=",
    "end_cursor": "WzM0M10=",
    "per_page": 500
  }
}

401 Response

{
  "errors": [
    "The access token is invalid"
  ]
}

404 Response

{
  "errors": [
    "Not Found"
  ]
}

200

Returns a paginated list of subscribers for the specified form

Response Schema: application/json

subscribersrequired
[object]
» idrequired
integer
» first_namerequired
any
» email_addressrequired
string
» staterequired
string
» created_atrequired
string
» added_atrequired
string
» fieldsrequired
object
»» categoryrequired
string
» referrer_utm_parameters
object
»» sourcerequired
string
»» mediumrequired
string
»» campaignrequired
string
»» termrequired
string
»» contentrequired
string
» referrer
string
paginationrequired
object
» has_previous_pagerequired
boolean
» has_next_pagerequired
boolean
» start_cursorrequired
string
» end_cursorrequired
string
» per_pagerequired
integer

401

Returns a 401 if the token and/or account cannot be authenticated

Response Schema: application/json

errorsrequired
[string]

404

Returns a 404 when the provided id does not exist

Response Schema: application/json

errorsrequired
[string]

Add subscriber to form by email address

Code samples

# You can also use wget
curl -X POST https://api.kit.com/v4/forms/{form_id}/subscribers \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN_HERE'

const inputBody = '{
  "email_address": "alice@convertkit.dev",
  "referrer": "https://mywebsite.com/bfpromo/?utm_source=facebook&utm_medium=cpc&utm_campaign=black_friday&utm_term=car_owners&utm_content=get_10_off"
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'Bearer YOUR_ACCESS_TOKEN_HERE'
};

fetch('https://api.kit.com/v4/forms/{form_id}/subscribers',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

result = RestClient.post 'https://api.kit.com/v4/forms/{form_id}/subscribers',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

r = requests.post('https://api.kit.com/v4/forms/{form_id}/subscribers', headers = headers)

print(r.json())

POST /v4/forms/{form_id}/subscribers

Body parameter

{
  "email_address": "alice@convertkit.dev",
  "referrer": "https://mywebsite.com/bfpromo/?utm_source=facebook&utm_medium=cpc&utm_campaign=black_friday&utm_term=car_owners&utm_content=get_10_off"
}

Parameters

AuthorizationsOAuth2, API Key

Path Parameters

form_idrequired
integer
Example: 194

Header Parameters

Authorizationrequired
string
Example: Bearer YOUR_ACCESS_TOKEN_HERE

Request Body Schemaapplication/json

email_addressrequired
string
referrer
string

Responses

Example responses

200 Response

{
  "subscriber": {
    "id": 441,
    "first_name": "Alice",
    "email_address": "alice@convertkit.dev",
    "state": "active",
    "created_at": "2023-02-17T11:43:55Z",
    "added_at": "2023-02-17T11:43:55Z",
    "fields": {},
    "referrer_utm_parameters": {
      "source": "facebook",
      "medium": "cpc",
      "campaign": "black_friday",
      "term": "car_owners",
      "content": "get_10_off"
    },
    "referrer": "https://mywebsite.com/bfpromo/?utm_source=facebook&utm_medium=cpc&utm_campaign=black_friday&utm_term=car_owners&utm_content=get_10_off"
  }
}

201 Response

{
  "subscriber": {
    "id": 442,
    "first_name": "Alice",
    "email_address": "alice@convertkit.dev",
    "state": "active",
    "created_at": "2023-02-17T11:43:55Z",
    "added_at": "2023-02-17T11:43:55Z",
    "fields": {},
    "referrer_utm_parameters": {
      "source": "facebook",
      "medium": "cpc",
      "campaign": "black_friday",
      "term": "car_owners",
      "content": "get_10_off"
    },
    "referrer": "https://mywebsite.com/bfpromo/?utm_source=facebook&utm_medium=cpc&utm_campaign=black_friday&utm_term=car_owners&utm_content=get_10_off"
  }
}

401 Response

{
  "errors": [
    "The access token is invalid"
  ]
}

404 Response

{
  "errors": [
    "Not Found"
  ]
}

422 Response

{
  "errors": [
    "Either subscriber id or email address is required to add subscriber to form"
  ]
}

200

Returns a 200 when the subscriber has already been added to the form

Response Schema: application/json

subscriberrequired
object
» idrequired
integer
» first_namerequired
string
» email_addressrequired
string
» staterequired
string
» created_atrequired
string
» added_atrequired
string
» fieldsrequired
object
» referrer_utm_parameters
object
»» sourcerequired
string
»» mediumrequired
string
»» campaignrequired
string
»» termrequired
string
»» contentrequired
string
» referrer
string

201

Adds the subscriber to the form

Response Schema: application/json

subscriberrequired
object
» idrequired
integer
» first_namerequired
string
» email_addressrequired
string
» staterequired
string
» created_atrequired
string
» added_atrequired
string
» fieldsrequired
object
» referrer_utm_parameters
object
»» sourcerequired
string
»» mediumrequired
string
»» campaignrequired
string
»» termrequired
string
»» contentrequired
string
» referrer
string

401

Returns a 401 if the token and/or account cannot be authenticated

Response Schema: application/json

errorsrequired
[string]

404

Returns a 404 when the provided id does not exist

Response Schema: application/json

errorsrequired
[string]

422

Returns a 422 with an error message when missing email address

Response Schema: application/json

errorsrequired
[string]

Add subscriber to form

Code samples

# You can also use wget
curl -X POST https://api.kit.com/v4/forms/{form_id}/subscribers/{id} \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN_HERE'

const inputBody = '{
  "referrer": "https://mywebsite.com/bfpromo/?utm_source=facebook&utm_medium=cpc&utm_campaign=black_friday&utm_term=car_owners&utm_content=get_10_off"
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'Bearer YOUR_ACCESS_TOKEN_HERE'
};

fetch('https://api.kit.com/v4/forms/{form_id}/subscribers/{id}',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

result = RestClient.post 'https://api.kit.com/v4/forms/{form_id}/subscribers/{id}',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

r = requests.post('https://api.kit.com/v4/forms/{form_id}/subscribers/{id}', headers = headers)

print(r.json())

POST /v4/forms/{form_id}/subscribers/{id}

Body parameter

{
  "referrer": "https://mywebsite.com/bfpromo/?utm_source=facebook&utm_medium=cpc&utm_campaign=black_friday&utm_term=car_owners&utm_content=get_10_off"
}

Parameters

AuthorizationsOAuth2, API Key

Path Parameters

form_idrequired
integer
Example: 174
idrequired
integer
Example: 425

Header Parameters

Authorizationrequired
string
Example: Bearer YOUR_ACCESS_TOKEN_HERE

Request Body Schemaapplication/json

referrerrequired
string

Responses

Example responses

200 Response

{
  "subscriber": {
    "id": 421,
    "first_name": "Alice",
    "email_address": "alice@convertkit.dev",
    "state": "active",
    "created_at": "2023-02-17T11:43:55Z",
    "added_at": "2023-02-17T11:43:55Z",
    "fields": {},
    "referrer_utm_parameters": {
      "source": "facebook",
      "medium": "cpc",
      "campaign": "black_friday",
      "term": "car_owners",
      "content": "get_10_off"
    },
    "referrer": "https://mywebsite.com/bfpromo/?utm_source=facebook&utm_medium=cpc&utm_campaign=black_friday&utm_term=car_owners&utm_content=get_10_off"
  }
}

201 Response

{
  "subscriber": {
    "id": 422,
    "first_name": "Alice",
    "email_address": "alice@convertkit.dev",
    "state": "active",
    "created_at": "2023-02-17T11:43:55Z",
    "added_at": "2023-02-17T11:43:55Z",
    "fields": {},
    "referrer_utm_parameters": {
      "source": "facebook",
      "medium": "cpc",
      "campaign": "black_friday",
      "term": "car_owners",
      "content": "get_10_off"
    },
    "referrer": "https://mywebsite.com/bfpromo/?utm_source=facebook&utm_medium=cpc&utm_campaign=black_friday&utm_term=car_owners&utm_content=get_10_off"
  }
}

401 Response

{
  "errors": [
    "The access token is invalid"
  ]
}

404 Response

{
  "errors": [
    "Not Found"
  ]
}

200

Returns a 200 when the subscriber has already been added to the form

Response Schema: application/json

subscriberrequired
object
» idrequired
integer
» first_namerequired
string
» email_addressrequired
string
» staterequired
string
» created_atrequired
string
» added_atrequired
string
» fieldsrequired
object
» referrer_utm_parameters
object
»» sourcerequired
string
»» mediumrequired
string
»» campaignrequired
string
»» termrequired
string
»» contentrequired
string
» referrer
string

201

Adds the subscriber to the form

Response Schema: application/json

subscriberrequired
object
» idrequired
integer
» first_namerequired
string
» email_addressrequired
string
» staterequired
string
» created_atrequired
string
» added_atrequired
string
» fieldsrequired
object
» referrer_utm_parameters
object
»» sourcerequired
string
»» mediumrequired
string
»» campaignrequired
string
»» termrequired
string
»» contentrequired
string
» referrer
string

401

Returns a 401 if the token and/or account cannot be authenticated

Response Schema: application/json

errorsrequired
[string]

404

Returns a 404 when the provided id does not exist

Response Schema: application/json

errorsrequired
[string]

Subscribers

Bulk create subscribers

Code samples

# You can also use wget
curl -X POST https://api.kit.com/v4/bulk/subscribers \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN_HERE'

const inputBody = '{
  "subscribers": [
    {
      "first_name": "Test Subscriber 0",
      "email_address": "subscriber_0@convertkit.dev"
    },
    {
      "first_name": "Test Subscriber 1",
      "email_address": "subscriber_1@convertkit.dev"
    },
    {
      "first_name": "Test Subscriber 2",
      "email_address": "subscriber_2@convertkit.dev"
    },
    {
      "first_name": "Test Subscriber 3",
      "email_address": "subscriber_3@convertkit.dev"
    }
  ],
  "callback_url": null
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'Bearer YOUR_ACCESS_TOKEN_HERE'
};

fetch('https://api.kit.com/v4/bulk/subscribers',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

result = RestClient.post 'https://api.kit.com/v4/bulk/subscribers',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

r = requests.post('https://api.kit.com/v4/bulk/subscribers', headers = headers)

print(r.json())

POST /v4/bulk/subscribers

See "Bulk & async processing" for more information.

Body parameter

{
  "subscribers": [
    {
      "first_name": "Test Subscriber 0",
      "email_address": "subscriber_0@convertkit.dev"
    },
    {
      "first_name": "Test Subscriber 1",
      "email_address": "subscriber_1@convertkit.dev"
    },
    {
      "first_name": "Test Subscriber 2",
      "email_address": "subscriber_2@convertkit.dev"
    },
    {
      "first_name": "Test Subscriber 3",
      "email_address": "subscriber_3@convertkit.dev"
    }
  ],
  "callback_url": null
}

Parameters

AuthorizationsOAuth2

Header Parameters

Authorizationrequired
string
Example: Bearer YOUR_ACCESS_TOKEN_HERE

Request Body Schemaapplication/json

subscribersrequired
[object]
» first_namerequired
string
» email_addressrequired
string
» state
string
Create subscriber in this state (active, bounced, cancelled, complained or inactive). Defaults to active.
callback_url
any

Responses

Example responses

200 Response

{
  "subscribers": [
    {
      "id": 290,
      "first_name": null,
      "email_address": "brooke@convertkit.dev",
      "state": "active",
      "created_at": "2023-02-17T11:43:55Z"
    },
    {
      "id": 291,
      "first_name": "Camille",
      "email_address": "camille@convertkit.dev",
      "state": "active",
      "created_at": "2023-02-17T11:43:55Z"
    },
    {
      "id": 289,
      "first_name": "Alice",
      "email_address": "alice@convertkit.dev",
      "state": "active",
      "created_at": "2023-02-17T11:43:55Z"
    }
  ],
  "failures": [
    {
      "subscriber": {
        "first_name": "Benito",
        "email_address": null,
        "state": "active",
        "created_at": null
      },
      "errors": [
        "Email address is invalid"
      ]
    }
  ]
}

202 Response

{}

401 Response

{
  "errors": [
    "The access token is invalid"
  ]
}

403 Response

{
  "errors": [
    "This request would exceed your subscriber limit"
  ]
}

413 Response

{
  "errors": [
    "This request exceeds your queued bulk requests limit. Please wait while we process your existing requests and try again later."
  ]
}

422 Response

{
  "errors": [
    "No subscribers included for processing"
  ]
}

200

Creates or updates the subscribers synchronously when 100 or less subscribers are requested

Response Schema: application/json

subscribersrequired
[object]
» idrequired
integer
» first_namerequired
any
» email_addressrequired
string
» staterequired
string
» created_at
string
failuresrequired
[object]
» subscriberrequired
object
»» first_namerequired
string
»» email_addressrequired
any
»» staterequired
string
»» created_at
any
» errorsrequired
[string]

202

Creates or updates subscribers asynchronously when more than 100 subscribers are requested

Response Schema: application/json

401

Returns a 401 if the token and/or account cannot be authenticated

Response Schema: application/json

errorsrequired
[string]

403

Returns a 403 when the number of subscribers in the request would exceed the account's subscriber limit

Response Schema: application/json

errorsrequired
[string]

413

Returns a 413 when the size of the request would exceed the account's data limit for enqueued bulk requests

Response Schema: application/json

errorsrequired
[string]

422

Returns a 422 when subscribers is empty or not an array

Response Schema: application/json

errorsrequired
[string]

List subscribers

Code samples

# You can also use wget
curl -X GET https://api.kit.com/v4/subscribers \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN_HERE'


const headers = {
  'Accept':'application/json',
  'Authorization':'Bearer YOUR_ACCESS_TOKEN_HERE'
};

fetch('https://api.kit.com/v4/subscribers',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

result = RestClient.get 'https://api.kit.com/v4/subscribers',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

r = requests.get('https://api.kit.com/v4/subscribers', headers = headers)

print(r.json())

GET /v4/subscribers

Parameters

AuthorizationsOAuth2, API Key

Query Parameters

after
any
Example: after=WzFd
To fetch next page of results, use ?after=<end_cursor>
before
any
Example: before=WzNd
To fetch previous page of results, use ?before=<start_cursor>
created_after
string
Example: created_after=2023-01-17T11:43:55Z
Filter subscribers who have been created after this date (format yyyy-mm-dd)
created_before
string
Example: created_before=2023-02-18T11:43:55Z
Filter subscribers who have been created before this date (format yyyy-mm-dd)
email_address
string
Example: email_address=alice@convertkit.dev
Search subscribers by email address. This is an exact match search.
include_total_count
string
Example: include_total_count=false
To include the total count of records in the response, use true. For large collections, expect a slightly slower response.
per_page
any
Example: per_page=10
Number of results per page. Default 500, maximum 1000.
sort_field
string
Example: sort_field=cancelled_at
Field to sort by (id, updated_at, cancelled_at). Defaults to id.
sort_order
string
Example: sort_order=asc
Sort order for results (asc or desc). Defaults to desc.
status
string
Example: status=bounced
Filter subscribers who have this status (active, inactive, bounced, complained, cancelled or all). Defaults to active.
updated_after
string
Example: updated_after=2023-01-17T11:43:55Z
Filter subscribers who have been updated after this date (format yyyy-mm-dd)
updated_before
string
Example: updated_before=2023-02-18T11:43:55Z
Filter subscribers who have been updated before this date (format yyyy-mm-dd)

Header Parameters

Authorizationrequired
string
Example: Bearer YOUR_ACCESS_TOKEN_HERE

Responses

Example responses

200 Response

{
  "subscribers": [
    {
      "id": 145,
      "first_name": "Alice",
      "email_address": "alice@convertkit.dev",
      "state": "active",
      "created_at": "2023-01-27T11:43:55Z",
      "fields": {
        "category": "One"
      }
    }
  ],
  "pagination": {
    "has_previous_page": false,
    "has_next_page": false,
    "start_cursor": "WzE0NV0=",
    "end_cursor": "WzE0NV0=",
    "per_page": 500
  }
}

401 Response

{
  "errors": [
    "The access token is invalid"
  ]
}

422 Response

{
  "errors": [
    "The status param must be `cancelled` if sort_field is `cancelled_at`"
  ]
}

200

Returns a list of subscribers matching the sort and filter params, defaulting to active subscribers sorted in descending order by id

Response Schema: application/json

subscribersrequired
[object]
» idrequired
integer
» first_namerequired
string
» email_addressrequired
string
» staterequired
string
» created_atrequired
string
» fieldsrequired
object
»» categoryrequired
string
paginationrequired
object
» has_previous_pagerequired
boolean
» has_next_pagerequired
boolean
» start_cursorrequired
string¦null
» end_cursorrequired
string¦null
» per_pagerequired
integer

401

Returns a 401 if the token and/or account cannot be authenticated

Response Schema: application/json

errorsrequired
[string]

422

raises an error when sorting on cancelled_at without the cancelled status

Response Schema: application/json

errorsrequired
[string]

Create a subscriber

Code samples

# You can also use wget
curl -X POST https://api.kit.com/v4/subscribers \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN_HERE'

const inputBody = '{
  "first_name": "Alice",
  "email_address": "alice@convertkit.dev",
  "state": "active",
  "fields": {
    "Last name": "Lamarr",
    "Birthday": "Feb 17",
    "Source": "landing page",
    "Role": "Software developer",
    "Company": "Convertkit",
    "Postal code": "83702",
    "Website": "convertkit.com",
    "Social media": "https://www.linkedin.com/company/convertkit",
    "How did you hear about us?": "Social media",
    "Interests": "Monetization",
    "Coupon": ""
  }
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'Bearer YOUR_ACCESS_TOKEN_HERE'
};

fetch('https://api.kit.com/v4/subscribers',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

result = RestClient.post 'https://api.kit.com/v4/subscribers',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

r = requests.post('https://api.kit.com/v4/subscribers', headers = headers)

print(r.json())

POST /v4/subscribers

Behaves as an upsert. If a subscriber with the provided email address does not exist, it creates one with the specified first name and state. If a subscriber with the provided email address already exists, it updates the first name.

We will ignore custom fields that don't already exist in your account. We will not return an error if you try to add data to a custom field that does not exist. Please use Create a custom field to create custom fields before setting for subscribers.

NOTE: Updating the subscriber state with this endpoint is not supported at this time.
NOTE: We support creating/updating a maximum of 140 custom fields at a time.

Body parameter

{
  "first_name": "Alice",
  "email_address": "alice@convertkit.dev",
  "state": "active",
  "fields": {
    "Last name": "Lamarr",
    "Birthday": "Feb 17",
    "Source": "landing page",
    "Role": "Software developer",
    "Company": "Convertkit",
    "Postal code": "83702",
    "Website": "convertkit.com",
    "Social media": "https://www.linkedin.com/company/convertkit",
    "How did you hear about us?": "Social media",
    "Interests": "Monetization",
    "Coupon": ""
  }
}

Parameters

AuthorizationsOAuth2, API Key

Header Parameters

Authorizationrequired
string
Example: Bearer YOUR_ACCESS_TOKEN_HERE

Request Body Schemaapplication/json

first_name
string or null
email_addressrequired
string
state
string or null
Create subscriber in this state (active, bounced, cancelled, complained or inactive). Defaults to active.
fields
object or null
» Last namerequired
string
» Birthdayrequired
string
» Sourcerequired
string
» Role
string
» Company
string
» Postal code
string
» Website
string
» Social media
string
» How did you hear about us?
string
» Interests
string
» Coupon
string

Responses

Example responses

200 Response

{
  "subscriber": {
    "id": 263,
    "first_name": "Alice",
    "email_address": "alice@convertkit.dev",
    "state": "inactive",
    "created_at": "2023-02-17T11:43:55Z",
    "fields": {}
  }
}

201 Response

{
  "subscriber": {
    "id": 261,
    "first_name": "Alice",
    "email_address": "alice@convertkit.dev",
    "state": "active",
    "created_at": "2023-02-17T11:43:55Z",
    "fields": {}
  }
}

202 Response

{
  "subscriber": {
    "id": 262,
    "first_name": "Alice",
    "email_address": "alice@convertkit.dev",
    "state": "active",
    "created_at": "2023-02-17T11:43:55Z",
    "fields": {}
  }
}

401 Response

{
  "errors": [
    "The access token is invalid"
  ]
}

422 Response

{
  "errors": [
    "Email address is invalid"
  ]
}

200

Returns a 200 and updates the subscriber first name when a subscriber with provided email already exists

Response Schema: application/json

subscriberrequired
object
» idrequired
integer
» first_namerequired
string
» email_addressrequired
string
» staterequired
string
» created_atrequired
string
» fieldsrequired
object

201

Creates a new subscriber

Response Schema: application/json

subscriberrequired
object
» idrequired
integer
» first_namerequired
string
» email_addressrequired
string
» staterequired
string
» created_atrequired
string
» fieldsrequired
object

202

Returns a 202 and asynchronously adds custom fields for the new subscriber when more than 10 custom fields are included in the request

Response Schema: application/json

subscriberrequired
object
» idrequired
integer
» first_namerequired
string
» email_addressrequired
string
» staterequired
string
» created_atrequired
string
» fieldsrequired
object

401

Returns a 401 if the token and/or account cannot be authenticated

Response Schema: application/json

errorsrequired
[string]

422

Returns a 422 with an error message when one or more of the parameters are invalid

Response Schema: application/json

errorsrequired
[string]

Get a subscriber

Code samples

# You can also use wget
curl -X GET https://api.kit.com/v4/subscribers/{id} \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN_HERE'


const headers = {
  'Accept':'application/json',
  'Authorization':'Bearer YOUR_ACCESS_TOKEN_HERE'
};

fetch('https://api.kit.com/v4/subscribers/{id}',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

result = RestClient.get 'https://api.kit.com/v4/subscribers/{id}',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

r = requests.get('https://api.kit.com/v4/subscribers/{id}', headers = headers)

print(r.json())

GET /v4/subscribers/{id}

Parameters

AuthorizationsOAuth2, API Key

Path Parameters

idrequired
integer
Example: 239

Header Parameters

Authorizationrequired
string
Example: Bearer YOUR_ACCESS_TOKEN_HERE

Responses

Example responses

200 Response

{
  "subscriber": {
    "id": 238,
    "first_name": "Alice",
    "email_address": "alice@convertkit.dev",
    "state": "active",
    "created_at": "2023-02-17T11:43:55Z",
    "fields": {
      "category": "One"
    }
  }
}

401 Response

{
  "errors": [
    "The access token is invalid"
  ]
}

404 Response

{
  "errors": [
    "Not Found"
  ]
}

200

Returns the subscriber details

Response Schema: application/json

subscriberrequired
object
» idrequired
integer
» first_namerequired
string
» email_addressrequired
string
» staterequired
string
» created_atrequired
string
» fieldsrequired
object
»» categoryrequired
string

401

Returns a 401 if the token and/or account cannot be authenticated

Response Schema: application/json

errorsrequired
[string]

404

Returns a 404 when the provided id does not exist

Response Schema: application/json

errorsrequired
[string]

Update a subscriber

Code samples

# You can also use wget
curl -X PUT https://api.kit.com/v4/subscribers/{id} \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN_HERE'

const inputBody = '{
  "first_name": "Alice",
  "email_address": "alice@convertkit.dev",
  "fields": {
    "Last name": "Lamarr",
    "Birthday": "Feb 17",
    "Source": "landing page",
    "Role": "Software developer",
    "Company": "Convertkit",
    "Postal code": "83702",
    "Website": "convertkit.com",
    "Social media": "https://www.linkedin.com/company/convertkit",
    "How did you hear about us?": "Social media",
    "Interests": "Monetization",
    "Coupon": ""
  }
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'Bearer YOUR_ACCESS_TOKEN_HERE'
};

fetch('https://api.kit.com/v4/subscribers/{id}',
{
  method: 'PUT',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

result = RestClient.put 'https://api.kit.com/v4/subscribers/{id}',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

r = requests.put('https://api.kit.com/v4/subscribers/{id}', headers = headers)

print(r.json())

PUT /v4/subscribers/{id}

We will ignore custom fields that don't already exist in your account. We will not return an error if you try to add data to a custom field that does not exist. Please use Create a custom field to create custom fields before setting for subscribers.

NOTE: We support creating/updating a maximum of 140 custom fields at a time.

Body parameter

{
  "first_name": "Alice",
  "email_address": "alice@convertkit.dev",
  "fields": {
    "Last name": "Lamarr",
    "Birthday": "Feb 17",
    "Source": "landing page",
    "Role": "Software developer",
    "Company": "Convertkit",
    "Postal code": "83702",
    "Website": "convertkit.com",
    "Social media": "https://www.linkedin.com/company/convertkit",
    "How did you hear about us?": "Social media",
    "Interests": "Monetization",
    "Coupon": ""
  }
}

Parameters

AuthorizationsOAuth2, API Key

Path Parameters

idrequired
integer
Example: 286

Header Parameters

Authorizationrequired
string
Example: Bearer YOUR_ACCESS_TOKEN_HERE

Request Body Schemaapplication/json

first_name
string or null
email_addressrequired
string
fields
object or null
» Last namerequired
string
» Birthdayrequired
string
» Sourcerequired
string
» Role
string
» Company
string
» Postal code
string
» Website
string
» Social media
string
» How did you hear about us?
string
» Interests
string
» Coupon
string

Responses

Example responses

200 Response

{
  "subscriber": {
    "id": 282,
    "first_name": "Alice",
    "email_address": "alice@convertkit.dev",
    "state": "active",
    "created_at": "2023-02-17T11:43:55Z",
    "fields": {}
  }
}

202 Response

{
  "subscriber": {
    "id": 283,
    "first_name": "Alice",
    "email_address": "alice@convertkit.dev",
    "state": "active",
    "created_at": "2023-02-17T11:43:55Z",
    "fields": {}
  }
}

401 Response

{
  "errors": [
    "The access token is invalid"
  ]
}

404 Response

{
  "errors": [
    "Not Found"
  ]
}

422 Response

{
  "errors": [
    "Email address has already been taken"
  ]
}

200

Updates the subscriber's email address and first name

Response Schema: application/json

subscriberrequired
object
» idrequired
integer
» first_namerequired
string
» email_addressrequired
string
» staterequired
string
» created_atrequired
string
» fieldsrequired
object

202

Returns a 202 and asynchronously updates custom fields for the subscriber when more than 10 custom fields are included in the request

Response Schema: application/json

subscriberrequired
object
» idrequired
integer
» first_namerequired
string
» email_addressrequired
string
» staterequired
string
» created_atrequired
string
» fieldsrequired
object

401

Returns a 401 if the token and/or account cannot be authenticated

Response Schema: application/json

errorsrequired
[string]

404

Returns a 404 when the provided id does not exist

Response Schema: application/json

errorsrequired
[string]

422

Returns 422 with an error when email address is already in use

Response Schema: application/json

errorsrequired
[string]

Unsubscribe subscriber

Code samples

# You can also use wget
curl -X POST https://api.kit.com/v4/subscribers/{id}/unsubscribe \
  -H 'Content-Type: application/json' \
  -H 'Accept: ' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN_HERE'

const inputBody = '{}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'',
  'Authorization':'Bearer YOUR_ACCESS_TOKEN_HERE'
};

fetch('https://api.kit.com/v4/subscribers/{id}/unsubscribe',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => '',
  'Authorization' => 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

result = RestClient.post 'https://api.kit.com/v4/subscribers/{id}/unsubscribe',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': '',
  'Authorization': 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

r = requests.post('https://api.kit.com/v4/subscribers/{id}/unsubscribe', headers = headers)

print(r.json())

POST /v4/subscribers/{id}/unsubscribe

Body parameter

{}

Parameters

AuthorizationsOAuth2, API Key

Path Parameters

idrequired
integer
Example: 256

Header Parameters

Authorizationrequired
string
Example: Bearer YOUR_ACCESS_TOKEN_HERE

Responses

Example responses

204 Response

401 Response

{
  "errors": [
    "The access token is invalid"
  ]
}

404 Response

{
  "errors": [
    "Not Found"
  ]
}

204

Unsubscribes the subscriber

401

Returns a 401 if the token and/or account cannot be authenticated

Response Schema: application/json

errorsrequired
[string]

404

Returns a 404 when the provided id does not exist

Response Schema: application/json

errorsrequired
[string]

List tags for a subscriber

Code samples

# You can also use wget
curl -X GET https://api.kit.com/v4/subscribers/{subscriber_id}/tags \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN_HERE'


const headers = {
  'Accept':'application/json',
  'Authorization':'Bearer YOUR_ACCESS_TOKEN_HERE'
};

fetch('https://api.kit.com/v4/subscribers/{subscriber_id}/tags',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

result = RestClient.get 'https://api.kit.com/v4/subscribers/{subscriber_id}/tags',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

r = requests.get('https://api.kit.com/v4/subscribers/{subscriber_id}/tags', headers = headers)

print(r.json())

GET /v4/subscribers/{subscriber_id}/tags

Parameters

AuthorizationsOAuth2, API Key

Path Parameters

subscriber_idrequired
integer
Example: 673

Query Parameters

after
any
before
any
include_total_count
string
Example: include_total_count=false
To include the total count of records in the response, use true. For large collections, expect a slightly slower response.
per_page
any

Header Parameters

Authorizationrequired
string
Example: Bearer YOUR_ACCESS_TOKEN_HERE

Responses

Example responses

200 Response

{
  "tags": [
    {
      "id": 88,
      "name": "Tag B",
      "tagged_at": "2023-02-17T10:43:55Z"
    },
    {
      "id": 89,
      "name": "Tag A",
      "tagged_at": "2023-02-17T10:43:55Z"
    }
  ],
  "pagination": {
    "has_previous_page": false,
    "has_next_page": false,
    "start_cursor": "WzZd",
    "end_cursor": "WzVd",
    "per_page": 500
  }
}

401 Response

{
  "errors": [
    "The access token is invalid"
  ]
}

404 Response

{
  "errors": [
    "Not Found"
  ]
}

200

Returns a paginated list of all tags for a subscriber

Response Schema: application/json

tagsrequired
[object]
» idrequired
integer
» namerequired
string
» added_at
string
» tagged_at
string
pagination
object
» has_previous_pagerequired
boolean
» has_next_pagerequired
boolean
» start_cursorrequired
string
» end_cursorrequired
string
» per_pagerequired
integer

401

Returns a 401 if the token and/or account cannot be authenticated

Response Schema: application/json

errorsrequired
[string]

404

Returns a 404 when the provided id does not exist

Response Schema: application/json

errorsrequired
[string]

Tags

Bulk create tags

Code samples

# You can also use wget
curl -X POST https://api.kit.com/v4/bulk/tags \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN_HERE'

const inputBody = '{
  "tags": [
    {
      "name": "Test Tag 0"
    },
    {
      "name": "Test Tag 1"
    },
    {
      "name": "Test Tag 2"
    },
    {
      "name": "Test Tag 3"
    }
  ],
  "callback_url": null
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'Bearer YOUR_ACCESS_TOKEN_HERE'
};

fetch('https://api.kit.com/v4/bulk/tags',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

result = RestClient.post 'https://api.kit.com/v4/bulk/tags',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

r = requests.post('https://api.kit.com/v4/bulk/tags', headers = headers)

print(r.json())

POST /v4/bulk/tags

See "Bulk & async processing" for more information.

Body parameter

{
  "tags": [
    {
      "name": "Test Tag 0"
    },
    {
      "name": "Test Tag 1"
    },
    {
      "name": "Test Tag 2"
    },
    {
      "name": "Test Tag 3"
    }
  ],
  "callback_url": null
}

Parameters

AuthorizationsOAuth2

Header Parameters

Authorizationrequired
string
Example: Bearer YOUR_ACCESS_TOKEN_HERE

Request Body Schemaapplication/json

tagsrequired
[object]
» namerequired
string
callback_url
any

Responses

Example responses

200 Response

{
  "tags": [
    {
      "id": 53,
      "name": "Attended Event",
      "created_at": "2023-02-17T11:43:55Z"
    },
    {
      "id": 54,
      "name": "Newsletter",
      "created_at": "2023-02-17T11:43:55Z"
    },
    {
      "id": 55,
      "name": "Re-engage",
      "created_at": "2023-02-17T11:43:55Z"
    }
  ],
  "failures": [
    {
      "tag": {
        "id": 52,
        "name": "Existing Tag",
        "created_at": "2023-02-17T11:43:55Z"
      },
      "errors": [
        "Name has already been taken"
      ]
    }
  ]
}

202 Response

{}

401 Response

{
  "errors": [
    "The access token is invalid"
  ]
}

413 Response

{
  "errors": [
    "This request exceeds your queued bulk requests limit. Please wait while we process your existing requests and try again later."
  ]
}

422 Response

{
  "errors": [
    "No tags included for processing"
  ]
}

200

Creates the tags synchronously when 100 or less tags are requested

Response Schema: application/json

tagsrequired
[object]
» idrequired
integer
» namerequired
string
» created_atrequired
string
failuresrequired
[object]
» tagrequired
object
»» idrequired
integer
»» namerequired
string
»» created_atrequired
string
» errorsrequired
[string]

202

Creates or updates tags asynchronously when more than 100 tags are requested

Response Schema: application/json

401

Returns a 401 if the token and/or account cannot be authenticated

Response Schema: application/json

errorsrequired
[string]

413

Returns a 413 when the size of the request would exceed the account's data limit for enqueued bulk requests

Response Schema: application/json

errorsrequired
[string]

422

Returns a 422 when tags is empty or not an array

Response Schema: application/json

errorsrequired
[string]

Bulk remove tags from subscribers

Code samples

# You can also use wget
curl -X DELETE https://api.kit.com/v4/bulk/tags/subscribers \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN_HERE'

const inputBody = '{
  "taggings": [
    {
      "tag_id": 0,
      "subscriber_id": 0
    },
    {
      "tag_id": 1,
      "subscriber_id": 1
    },
    {
      "tag_id": 2,
      "subscriber_id": 2
    },
    {
      "tag_id": 3,
      "subscriber_id": 3
    }
  ],
  "callback_url": null
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'Bearer YOUR_ACCESS_TOKEN_HERE'
};

fetch('https://api.kit.com/v4/bulk/tags/subscribers',
{
  method: 'DELETE',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

result = RestClient.delete 'https://api.kit.com/v4/bulk/tags/subscribers',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

r = requests.delete('https://api.kit.com/v4/bulk/tags/subscribers', headers = headers)

print(r.json())

DELETE /v4/bulk/tags/subscribers

See "Bulk & async processing" for more information.

Body parameter

{
  "taggings": [
    {
      "tag_id": 0,
      "subscriber_id": 0
    },
    {
      "tag_id": 1,
      "subscriber_id": 1
    },
    {
      "tag_id": 2,
      "subscriber_id": 2
    },
    {
      "tag_id": 3,
      "subscriber_id": 3
    }
  ],
  "callback_url": null
}

Parameters

AuthorizationsOAuth2

Header Parameters

Authorizationrequired
string
Example: Bearer YOUR_ACCESS_TOKEN_HERE

Request Body Schemaapplication/json

taggingsrequired
[object]
» tag_idrequired
integer
» subscriber_idrequired
integer
callback_url
any

Responses

Example responses

200 Response

{
  "failures": []
}

202 Response

{}

401 Response

{
  "errors": [
    "The access token is invalid"
  ]
}

413 Response

{
  "errors": [
    "This request exceeds your queued bulk requests limit. Please wait while we process your existing requests and try again later."
  ]
}

422 Response

{
  "errors": [
    "No taggings included for processing"
  ]
}

200

Deletes the taggings synchronously when 100 or less tags/subscribers are provided

Response Schema: application/json

failuresrequired
[any]

202

Destroys taggings asynchronously when more than 100 tags/subscribers are provided

Response Schema: application/json

401

Returns a 401 if the token and/or account cannot be authenticated

Response Schema: application/json

errorsrequired
[string]

413

Returns a 413 when the size of the request would exceed the account's data limit for enqueued bulk requests

Response Schema: application/json

errorsrequired
[string]

422

Returns a 422 when taggings is empty or not an array

Response Schema: application/json

errorsrequired
[string]

Bulk tag subscribers

Code samples

# You can also use wget
curl -X POST https://api.kit.com/v4/bulk/tags/subscribers \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN_HERE'

const inputBody = '{
  "taggings": [
    {
      "tag_id": 0,
      "subscriber_id": 0
    },
    {
      "tag_id": 1,
      "subscriber_id": 1
    },
    {
      "tag_id": 2,
      "subscriber_id": 2
    },
    {
      "tag_id": 3,
      "subscriber_id": 3
    }
  ],
  "callback_url": null
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'Bearer YOUR_ACCESS_TOKEN_HERE'
};

fetch('https://api.kit.com/v4/bulk/tags/subscribers',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

result = RestClient.post 'https://api.kit.com/v4/bulk/tags/subscribers',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

r = requests.post('https://api.kit.com/v4/bulk/tags/subscribers', headers = headers)

print(r.json())

POST /v4/bulk/tags/subscribers

See "Bulk & async processing" for more information.

Body parameter

{
  "taggings": [
    {
      "tag_id": 0,
      "subscriber_id": 0
    },
    {
      "tag_id": 1,
      "subscriber_id": 1
    },
    {
      "tag_id": 2,
      "subscriber_id": 2
    },
    {
      "tag_id": 3,
      "subscriber_id": 3
    }
  ],
  "callback_url": null
}

Parameters

AuthorizationsOAuth2

Header Parameters

Authorizationrequired
string
Example: Bearer YOUR_ACCESS_TOKEN_HERE

Request Body Schemaapplication/json

taggingsrequired
[object]
» tag_idrequired
integer
» subscriber_idrequired
integer
callback_url
any

Responses

Example responses

200 Response

{
  "subscribers": [
    {
      "id": 322,
      "first_name": "Sub",
      "email_address": "sub@example.com",
      "created_at": "2023-02-17T11:43:55Z",
      "tagged_at": "2023-02-17T11:43:55Z"
    },
    {
      "id": 322,
      "first_name": "Sub",
      "email_address": "sub@example.com",
      "created_at": "2023-02-17T11:43:55Z",
      "tagged_at": "2023-02-17T11:43:55Z"
    }
  ],
  "failures": []
}

202 Response

{}

401 Response

{
  "errors": [
    "The access token is invalid"
  ]
}

413 Response

{
  "errors": [
    "This request exceeds your queued bulk requests limit. Please wait while we process your existing requests and try again later."
  ]
}

422 Response

{
  "errors": [
    "No taggings included for processing"
  ]
}

200

Creates the taggings synchronously when 100 or less tags/subscribers are requested

Response Schema: application/json

subscribersrequired
[object]
» idrequired
integer
» first_namerequired
string
» email_addressrequired
string
» created_atrequired
string
» tagged_atrequired
string
failuresrequired
[any]

202

Creates or updates taggings asynchronously when more than 100 tags/subscribers are requested

Response Schema: application/json

401

Returns a 401 if the token and/or account cannot be authenticated

Response Schema: application/json

errorsrequired
[string]

413

Returns a 413 when the size of the request would exceed the account's data limit for enqueued bulk requests

Response Schema: application/json

errorsrequired
[string]

422

Returns a 422 when taggings is empty or not an array

Response Schema: application/json

errorsrequired
[string]

List tags

Code samples

# You can also use wget
curl -X GET https://api.kit.com/v4/tags \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN_HERE'


const headers = {
  'Accept':'application/json',
  'Authorization':'Bearer YOUR_ACCESS_TOKEN_HERE'
};

fetch('https://api.kit.com/v4/tags',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

result = RestClient.get 'https://api.kit.com/v4/tags',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

r = requests.get('https://api.kit.com/v4/tags', headers = headers)

print(r.json())

GET /v4/tags

Parameters

AuthorizationsOAuth2, API Key

Query Parameters

after
any
Example: after=WzFd
To fetch next page of results, use ?after=<end_cursor>
before
any
Example: before=WzNd
To fetch previous page of results, use ?before=<start_cursor>
include_total_count
string
Example: include_total_count=false
To include the total count of records in the response, use true. For large collections, expect a slightly slower response.
per_page
any
Example: per_page=10
Number of results per page. Default 500, maximum 1000.

Header Parameters

Authorizationrequired
string
Example: Bearer YOUR_ACCESS_TOKEN_HERE

Responses

Example responses

200 Response

{
  "tags": [
    {
      "id": 5,
      "name": "Tag B",
      "created_at": "2023-02-17T11:43:55Z"
    },
    {
      "id": 4,
      "name": "Tag A",
      "created_at": "2023-02-17T11:43:55Z"
    }
  ],
  "pagination": {
    "has_previous_page": false,
    "has_next_page": false,
    "start_cursor": "WzVd",
    "end_cursor": "WzRd",
    "per_page": 500
  }
}

401 Response

{
  "errors": [
    "The access token is invalid"
  ]
}

200

Returns a paginated list of all tags for your account

Response Schema: application/json

tagsrequired
[object]
» idrequired
integer
» namerequired
string
» created_atrequired
string
paginationrequired
object
» has_previous_pagerequired
boolean
» has_next_pagerequired
boolean
» start_cursorrequired
string
» end_cursorrequired
string
» per_pagerequired
integer

401

Returns a 401 if the token and/or account cannot be authenticated

Response Schema: application/json

errorsrequired
[string]

Create a tag

Code samples

# You can also use wget
curl -X POST https://api.kit.com/v4/tags \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN_HERE'

const inputBody = '{
  "name": "Completed"
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'Bearer YOUR_ACCESS_TOKEN_HERE'
};

fetch('https://api.kit.com/v4/tags',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

result = RestClient.post 'https://api.kit.com/v4/tags',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

r = requests.post('https://api.kit.com/v4/tags', headers = headers)

print(r.json())

POST /v4/tags

Body parameter

{
  "name": "Completed"
}

Parameters

AuthorizationsOAuth2, API Key

Header Parameters

Authorizationrequired
string
Example: Bearer YOUR_ACCESS_TOKEN_HERE

Request Body Schemaapplication/json

namerequired
string

Responses

Example responses

201 Response

{
  "tag": {
    "id": 11,
    "name": "Completed",
    "created_at": "2023-02-17T11:43:55Z"
  }
}

401 Response

{
  "errors": [
    "The access token is invalid"
  ]
}

422 Response

{
  "errors": [
    "Name has already been taken"
  ]
}

201

Creates the tag

Response Schema: application/json

tagrequired
object
» idrequired
integer
» namerequired
string
» created_atrequired
string

401

Returns a 401 if the token and/or account cannot be authenticated

Response Schema: application/json

errorsrequired
[string]

422

Returns a 422 with an error message when the tag already exists

Response Schema: application/json

errorsrequired
[string]

Update tag name

Code samples

# You can also use wget
curl -X PUT https://api.kit.com/v4/tags/{id} \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN_HERE'

const inputBody = '{
  "name": "signed up"
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'Bearer YOUR_ACCESS_TOKEN_HERE'
};

fetch('https://api.kit.com/v4/tags/{id}',
{
  method: 'PUT',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

result = RestClient.put 'https://api.kit.com/v4/tags/{id}',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

r = requests.put('https://api.kit.com/v4/tags/{id}', headers = headers)

print(r.json())

PUT /v4/tags/{id}

Body parameter

{
  "name": "signed up"
}

Parameters

AuthorizationsOAuth2, API Key

Path Parameters

idrequired
integer
Example: 30

Header Parameters

Authorizationrequired
string
Example: Bearer YOUR_ACCESS_TOKEN_HERE

Request Body Schemaapplication/json

namerequired
string

Responses

Example responses

200 Response

{
  "tag": {
    "id": 28,
    "name": "signed up",
    "created_at": "2024-11-25T22:01:05Z"
  }
}

401 Response

{
  "errors": [
    "The access token is invalid"
  ]
}

404 Response

{
  "errors": [
    "Not Found"
  ]
}

422 Response

{
  "errors": [
    "Name can't be blank"
  ]
}

200

Updates the tag name

Response Schema: application/json

tagrequired
object
» idrequired
integer
» namerequired
string
» created_atrequired
string

401

Returns a 401 if the token and/or account cannot be authenticated

Response Schema: application/json

errorsrequired
[string]

404

Returns a 404 when the provided id does not exist

Response Schema: application/json

errorsrequired
[string]

422

Returns a 422 with an error message when name is invalid

Response Schema: application/json

errorsrequired
[string]

Remove tag from subscriber by email address

Code samples

# You can also use wget
curl -X DELETE https://api.kit.com/v4/tags/{tag_id}/subscribers \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -H 'Accept: ' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN_HERE'

const inputBody = '{
  "email_address": "alice@convertkit.dev"
}';
const headers = {
  'Content-Type':'application/x-www-form-urlencoded',
  'Accept':'',
  'Authorization':'Bearer YOUR_ACCESS_TOKEN_HERE'
};

fetch('https://api.kit.com/v4/tags/{tag_id}/subscribers',
{
  method: 'DELETE',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/x-www-form-urlencoded',
  'Accept' => '',
  'Authorization' => 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

result = RestClient.delete 'https://api.kit.com/v4/tags/{tag_id}/subscribers',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/x-www-form-urlencoded',
  'Accept': '',
  'Authorization': 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

r = requests.delete('https://api.kit.com/v4/tags/{tag_id}/subscribers', headers = headers)

print(r.json())

DELETE /v4/tags/{tag_id}/subscribers

Body parameter

email_address: alice@convertkit.dev

Parameters

AuthorizationsOAuth2, API Key

Path Parameters

tag_idrequired
integer
Example: 207

Header Parameters

Authorizationrequired
string
Example: Bearer YOUR_ACCESS_TOKEN_HERE

Request Body Schemaapplication/json

email_addressrequired
string

Responses

Example responses

204 Response

401 Response

{
  "errors": [
    "The access token is invalid"
  ]
}

404 Response

{
  "errors": [
    "Not Found"
  ]
}

422 Response

{
  "errors": [
    "Either subscriber id or email address is required to remove tag from subscriber"
  ]
}

204

Removes the tag from the subscriber

401

Returns a 401 if the token and/or account cannot be authenticated

Response Schema: application/json

errorsrequired
[string]

404

Returns a 404 when the provided id does not exist

Response Schema: application/json

errorsrequired
[string]

422

Returns a 422 with an error message when missing email address

Response Schema: application/json

errorsrequired
[string]

List subscribers for a tag

Code samples

# You can also use wget
curl -X GET https://api.kit.com/v4/tags/{tag_id}/subscribers \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN_HERE'


const headers = {
  'Accept':'application/json',
  'Authorization':'Bearer YOUR_ACCESS_TOKEN_HERE'
};

fetch('https://api.kit.com/v4/tags/{tag_id}/subscribers',
{
  method: 'GET',

  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Accept' => 'application/json',
  'Authorization' => 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

result = RestClient.get 'https://api.kit.com/v4/tags/{tag_id}/subscribers',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Accept': 'application/json',
  'Authorization': 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

r = requests.get('https://api.kit.com/v4/tags/{tag_id}/subscribers', headers = headers)

print(r.json())

GET /v4/tags/{tag_id}/subscribers

Parameters

AuthorizationsOAuth2, API Key

Path Parameters

tag_idrequired
integer
Example: 114

Query Parameters

after
any
Example: after=WzFd
To fetch next page of results, use ?after=<end_cursor>
before
any
Example: before=WzNd
To fetch previous page of results, use ?before=<start_cursor>
created_after
any
Example: created_after=2023-01-17T11:43:55Z
Filter subscribers who have been created after this date (format yyyy-mm-dd)
created_before
any
Example: created_before=2023-02-18T11:43:55Z
Filter subscribers who have been created before this date (format yyyy-mm-dd)
include_total_count
string
Example: include_total_count=false
To include the total count of records in the response, use true. For large collections, expect a slightly slower response.
per_page
any
Example: per_page=10
Number of results per page. Default 500, maximum 1000.
status
string
Example: status=all
Filter subscribers who have this status (active, inactive, bounced, complained, cancelled or all). Defaults to active.
tagged_after
any
Example: tagged_after=2023-02-14T11:43:55Z
Filter subscribers who have been tagged after this date (format yyyy-mm-dd)
tagged_before
any
Example: tagged_before=2023-02-18T11:43:55Z
Filter subscribers who have been tagged before this date (format yyyy-mm-dd)

Header Parameters

Authorizationrequired
string
Example: Bearer YOUR_ACCESS_TOKEN_HERE

Responses

Example responses

200 Response

{
  "subscribers": [
    {
      "id": 676,
      "first_name": null,
      "email_address": "subscriber329@convertkit.dev",
      "state": "active",
      "created_at": "2023-02-17T11:43:55Z",
      "tagged_at": "2023-02-17T11:43:55Z",
      "fields": {
        "category": "One"
      }
    },
    {
      "id": 675,
      "first_name": null,
      "email_address": "subscriber328@convertkit.dev",
      "state": "active",
      "created_at": "2023-02-17T11:43:55Z",
      "tagged_at": "2023-02-17T11:43:55Z",
      "fields": {
        "category": null
      }
    },
    {
      "id": 674,
      "first_name": null,
      "email_address": "subscriber327@convertkit.dev",
      "state": "active",
      "created_at": "2023-02-17T11:43:55Z",
      "tagged_at": "2023-02-17T11:43:55Z",
      "fields": {
        "category": null
      }
    }
  ],
  "pagination": {
    "has_previous_page": false,
    "has_next_page": false,
    "start_cursor": "WyIyMDIzLTAyLTE3VDExOjQzOjU1LjAwMFoiLDExXQ==",
    "end_cursor": "WyIyMDIzLTAyLTE3VDExOjQzOjU1LjAwMFoiLDld",
    "per_page": 500
  }
}

401 Response

{
  "errors": [
    "The access token is invalid"
  ]
}

404 Response

{
  "errors": [
    "Not Found"
  ]
}

200

Returns a paginated list of subscribers for the specified tag

Response Schema: application/json

subscribersrequired
[object]
» idrequired
integer
» first_namerequired
any
» email_addressrequired
string
» staterequired
string
» created_atrequired
string
» tagged_atrequired
string
» fieldsrequired
object
»» categoryrequired
string
paginationrequired
object
» has_previous_pagerequired
boolean
» has_next_pagerequired
boolean
» start_cursorrequired
string¦null
» end_cursorrequired
string¦null
» per_pagerequired
integer

401

Returns a 401 if the token and/or account cannot be authenticated

Response Schema: application/json

errorsrequired
[string]

404

Returns a 404 when the provided id does not exist

Response Schema: application/json

errorsrequired
[string]

Tag a subscriber by email address

Code samples

# You can also use wget
curl -X POST https://api.kit.com/v4/tags/{tag_id}/subscribers \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer YOUR_ACCESS_TOKEN_HERE'

const inputBody = '{
  "email_address": "alice@convertkit.dev"
}';
const headers = {
  'Content-Type':'application/json',
  'Accept':'application/json',
  'Authorization':'Bearer YOUR_ACCESS_TOKEN_HERE'
};

fetch('https://api.kit.com/v4/tags/{tag_id}/subscribers',
{
  method: 'POST',
  body: inputBody,
  headers: headers
})
.then(function(res) {
    return res.json();
}).then(function(body) {
    console.log(body);
});

require 'rest-client'
require 'json'

headers = {
  'Content-Type' => 'application/json',
  'Accept' => 'application/json',
  'Authorization' => 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

result = RestClient.post 'https://api.kit.com/v4/tags/{tag_id}/subscribers',
  params: {
  }, headers: headers

p JSON.parse(result)

import requests
headers = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
  'Authorization': 'Bearer YOUR_ACCESS_TOKEN_HERE'
}

r = requests.post('https://api.kit.com/v4/tags/{tag_id}/subscribers', headers = headers)

print(r.json())

POST /v4/tags/{tag_id}/subscribers

Body parameter

{
  "email_address": "alice@convertkit.dev"
}

Parameters

AuthorizationsOAuth2, API Key

Path Parameters

tag_idrequired
integer
Example: 168

Header Parameters

Authorizationrequired
string
Example: Bearer YOUR_ACCESS_TOKEN_HERE

Request Body Schemaapplication/json

email_addressrequired
string

Responses

Example responses

200 Response

{
  "subscriber": {
    "id": 770,
    "first_name": "Alice",
    "email_address": "alice@convertkit.dev",
    "state": "active",
    "created_at": "2023-02-17T11:43:55Z",
    "tagged_at": "2023-02-17T11:43:55Z",
    "fields": {}
  }
}

201 Response

{
  "subscriber": {
    "id": 771,
    "first_name": "Alice",
    "email_address": "alice@convertkit.dev",
    "state": "active",
    "created_at": "2023-02-17T11:43:55Z",
    "tagged_at": "2023-02-17T11:43:55Z",
    "fields": {}
  }
}

401 Response

{
  "errors": [
    "The access token is invalid"
  ]
}

404 Response

{
  "errors": [
    "Not Found"
  ]
}

422 Response

{
  "errors": [
    "Either subscriber id or email address is required to tag subscriber"
  ]
}

200

Returns a 200 when the subscriber already has the tag

Response Schema: application/json

subscriberrequired
object
» idrequired
integer
» first_namerequired
string
» email_addressrequired
string
» staterequired
string
» created_atrequired
string
» tagged_atrequired
string
» fieldsrequired
object

201

Tags the subscriber

Response Schema: application/json

subscriberrequired
object
» idrequired
integer
» first_namerequired
string
» email_addressrequired
string
» staterequired
string
» created_atrequired
string