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:
- Improved performance
- Cursor-based pagination
- Bulk requests and async processing
- New functionality for broadcasts, including access to subscriber filters and improved HTML support
- Bug fixes
See our guide on upgrading from V3 to V4.
Authentication
We support two authentication mechanisms in the V4 API:
- OAuth 2.0 for apps available for all creators in our App Store
- API Keys for automating simple tools and integrations for your account
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:
- Purchases endpoint
- Bulk endpoints
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:
- For web servers, you'll use the refresh token flow
- For Single Page Apps (SPA) or mobile apps, you'll use the Proof Key for Code Exchange (PKCE) flow
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)
Inactive
: unconfirmed subscriber that cannot be emailed until activated. To activate, the subscriber will need to be added to a form with double opt-in enabled and confirm their subscription.Active
: confirmed subscriber that can be emailed and counts towards billing totals.Cancelled
: subscriber that has unsubscribed from the account. Cancelled subscribers cannot be contacted but can be re-subscribed at a later date - these don’t count towards billing totals.Bounced
: subscriber that has triggered a hard bounce due to a permanent issue that restricts them from receiving emails. These are unsubscribed automatically and don’t count towards billing totals.Complained
: subscriber that has marked an email as spam. This cancels their subscriptions to any forms, landing pages, or sequences and removes them from your list.
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
- The URLs for the API endpoints are now
api.kit.com/v4/...
instead ofapi.convertkit.com/v3/...
. They are otherwise unchanged unless called out specifically below. - V4 supports OAuth for applications and API Keys for automating simple tools and integrations for your personal account. V4 API Keys are not compatible with V3
- Our pagination mechanism has changed. We no longer support page or offset based pagination. All of our pagination is now cursor based. This improves performance.
- All errors are now returned with a consistent response shape. The response is a JSON
object with a single attribute
errors
, an array of strings. - See below for a list of endpoints changed
Accounts
- Get current account
- The response shape has changed. User and account information is now nested under
user
andaccount
objects, respectively.
- The response shape has changed. User and account information is now nested under
Broadcasts
- List broadcasts
- The
page
parameter is no longer supported. To request next or previous pages, use thebefore
orafter
cursor
- The
- Create a broadcast
- The
email_layout_template
param is no longer supported. To specify the email template, use theemail_template_id
param. - Query your email templates to get the correct id
- The response shape has changed. We no longer return
email_layout_template
and return an object foremail_template
. - The error response shape has changed.
- The
- Get a broadcast
- The response shape has changed. We no longer return
email_layout_template
and return an object foremail_template
. - The error response shape has changed.
- The response shape has changed. We no longer return
- Delete a broadcast
- The response shape has changed. We return a 204 empty response.
- The error response shape has changed.
- Update a broadcast
- The
email_layout_template
param is no longer supported. To specify the email template, use theemail_template_id
param. - Query your email templates to get the correct id
- The response shape has changed. We no longer return
email_layout_template
and return an object foremail_template
. - The error response shape has changed.
- The
- Get stats
- The error response shape has changed.
Subscribers
- List subscribers
- The
page
parameter is no longer supported. To request next or previous pages, use thebefore
orafter
cursor - The
from
parameter is no longer supported. It has been replaced withcreated_after
. - The
to
parameter is no longer supported. It has been replaced withcreated_before
. - The
updated_from
parameter is no longer supported. It has been replaced withupdated_after
. - The
updated_to
parameter is no longer supported. It has been replaced withupdated_before
.
- The
- Get a subscriber
- The error response shape has changed.
- Update a subscriber
- The error response shape has changed.
- Unsubscribe a subscriber
- The URL path has changed.
/v3/unsubscribe
->/v4/subscribers/:id/unsubscribe
- We now require you to unsubscribe the subscriber via their id
- If you need to find their id by email address, you can query with List subscribers,
/v4/subscribers?email_address=<email>
- The response shape has changed. It returns a 204 empty response instead of the subscriber.
- The error response shape has changed.
- The URL path has changed.
- List tags for a subscriber
- The response shape has changed.
created_at
has been replaced withtagged_at
. - The error response shape has changed.
- The response shape has changed.
Custom Fields
- Create a custom field
- The response shape has changed. The created custom field is now returned nested under a
custom_field
attribute. - This endpoint no longer allows creating multiple custom fields. Use Bulk create custom fields instead.
- The error response shape has changed.
- The response shape has changed. The created custom field is now returned nested under a
- Update a custom field
- The response shape has changed. The updated custom field is returned nested under a
custom_field
attribute. - The error response shape has changed.
- The response shape has changed. The updated custom field is returned nested under a
Forms
- List forms
- Add subscriber to a form by email address
- The
email
parameter is no longer supported. To add a subscriber by email address, use theemail_address
parameter.
- The
- List subscribers to a form
- The URL path has changed.
/v3/forms/:id/subscriptions
->/v4/forms/:id/subscribers
- The response shape has changed. Subscriber information is no longer nested under
subscription
.
- The URL path has changed.
Purchases
- List purchases
- The
page
parameter is no longer supported. To request next or previous pages, use thebefore
orafter
cursor
- The
- Create a purchase
- The error response shape has changed.
Sequences
- List sequences
- The response shape has changed. Sequences are nested under a
sequences
attributes (instead of acourses
attribute).
- The response shape has changed. Sequences are nested under a
- Add subscriber to a sequence by email address
- The
email
parameter is no longer supported. To add a subscriber by email address, use theemail_address
parameter.
- The
- List subscribers to a sequence
- The URL path has changed.
/v3/sequences/:id/subscriptions
->/v4/sequences/:id/subscribers
- The response shape has changed. Subscriber information is no longer nested under
subscription
.
- The URL path has changed.
Tags
- Create a tag
- The request shape has changed. Root
tag
attribute no longer required - The response shape has changed. The returned tag is nested under a
tag
attribute. - The error response shape has changed.
- This endpoint no longer allows creating multiple tags. Use Bulk create tags instead.
- The request shape has changed. Root
- List subscribers for a tag
- The URL path has changed.
/v3/tags/:id/subscriptions
->/v4/tags/:id/subscribers
- The
page
parameter is no longer supported. To request next or previous pages, use thebefore
orafter
cursor - The error response shape has changed.
- The response shape has changed. The root object is
subscribers
instead ofsubscriptions
along with other smaller changes.
- The URL path has changed.
- Tag a subscriber
- The URL path has changed.
/v3/tags/:id/subscribe
->/v4/tags/:tag_id/subscribers/:id
- The response shape has changed. The root object is
subscriber
instead ofsubscription
along with other smaller changes. - The error response shape has changed.
- None of the optional params from V3 are supported in V4
- The URL path has changed.
- Tag a subscriber by email address
- The URL path has changed.
/v3/tags/:id/subscribe
->/v4/tags/:tag_id/subscribers
- The
email
parameter is no longer supported. To add a subscriber by email address, use theemail_address
parameter. - The response shape has changed. The root object is
subscriber
instead ofsubscription
along with other smaller changes. - The error response shape has changed.
- None of the optional request params from V3 are supported in V4
- The URL path has changed.
- Remove tag from subscriber
- The URL path and HTTP verb has changed.
POST /v3/tags/:id/unsubscribe
->DELETE /v4/tags/:tag_id/subscribers/:id
- The response shape has changed. We return a 204 empty response
- The error response shape has changed.
- The URL path and HTTP verb has changed.
- Remove tag from subscriber by email address
- The URL path and HTTP verb has changed.
POST /v3/tags/:id/unsubscribe
->DELETE /v4/tags/:tag_id/subscribers/:id
- The response shape has changed. We return a 204 empty response.
- The error response shape has changed.
- The URL path and HTTP verb has changed.
Webhooks
- The URL paths for webhooks have changed from
/automations/hooks
to/webhooks
. - Create a webhook
- The response shape has changed. The root object is
webhook
instead ofrule
. - The error response shape has changed.
- The response shape has changed. The root object is
- Delete a webhook
- The response shape has changed. We return a 204 empty response.
- The error response shape has changed.
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.
|
3. Kit prompts user for consent
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
|
4. Kit prompts user for consent
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:
- You would create an API endpoint to generate the HTML for your Product embed.
- You would create an API endpoint for users to search products in their account
- 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
- A user would install your app from Kit's App Store
- They would complete the authorization process for your site/API and we'll store their authorization data (tokens, etc.)
- They open Kit's editor and insert your Product element.
- 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.
- 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.
Logo
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
}
]
}
}
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:
- Click the refresh button that appears when hovering over the element (pictured below), or
- Change one of your plugin’s settings in the sidebar, which will automatically kick off another request for new HTML.
Plugin Authorization
We currently support 2 authorization strategies for requesting data from your API.
- You can choose to create a publicly accessible API with no authorization (not recommended).
- Or you can create an API that supports OAuth 2.0.
OAuth Plugin
For OAuth, you'll need to support 4 endpoints
- Getting an authorization code grant
- Requesting an access token using an authorization code
- Requesting an access token using a refresh token
- Revoking an access token
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
https://app.kit.com/apps
with authorization code parameterGet 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:
- Scripts, iframes
- Audio, video elements
- Form, input, command, action, prompt elements
- External CSS styles, and CSS URLs
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>
- For email client compatibility, we suggest that you use inline
style
attributes such as<div style="color: red;"></div>
instead of CSS classes.- The only exception is if you need to include media queries to make your elements responsive on mobile
- To test email client compatibility, we recommend using https://www.caniemail.com and https://www.litmus.com/
Include
target=_blank
to all linksUse the full path URL for all links to ensure they can be opened
In most cases, you shouldn’t apply a background color to your plugin (unless the user is able to customize it). This is because the user might be using a custom background color on their email. By not applying a background color, your element’s background will automatically be the same as their email.
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"
]
}
Returns current account and user info
200
Response Schema: application/json
userrequired
» emailrequired
accountrequired
» namerequired
» plan_typerequired
» primary_email_addressrequired
» created_at
» id
Returns a 401 if the token and/or account cannot be authenticated
401
Response Schema: application/json
errorsrequired
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"
]
}
Returns list of colors for the current account
200
Response Schema: application/json
colorsrequired
Returns a 401 if the token and/or account cannot be authenticated
401
Response Schema: application/json
errorsrequired
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."
]
}
Updates and returns list of colors for the current account
200
Response Schema: application/json
colorsrequired
Returns a 401 if the token and/or account cannot be authenticated
401
Response Schema: application/json
errorsrequired
Returns a 422 with an error message when invalid color code is provided
422
Response Schema: application/json
errorsrequired
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"
]
}
Returns Creator Profile details
200
Response Schema: application/json
profilerequired
» namerequired
» bylinerequired
» biorequired
» image_urlrequired
» profile_urlrequired
Returns a 401 if the token and/or account cannot be authenticated
401
Response Schema: application/json
errorsrequired
Returns a 404 if the creator profile doesn't exist
404
Response Schema: application/json
errorsrequired
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"
]
}
Returns your email stats for the last 90 days
200
Response Schema: application/json
statsrequired
» sentrequired
» clickedrequired
» openedrequired
» email_stats_moderequired
» open_tracking_enabledrequired
» click_tracking_enabledrequired
» startingrequired
» endingrequired
Returns a 401 if the token and/or account cannot be authenticated
401
Response Schema: application/json
errorsrequired
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."
]
}
Returns your growth stats for the provided starting and ending dates
200
Response Schema: application/json
statsrequired
» cancellationsrequired
» net_new_subscribersrequired
» new_subscribersrequired
» subscribersrequired
» startingrequired
» endingrequired
Returns a 401 if the token and/or account cannot be authenticated
401
Response Schema: application/json
errorsrequired
Returns a 422 with an error message if the starting or ending params are misformatted or the range is invalid
422
Response Schema: application/json
errorsrequired
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"
]
}
Returns a paginated list of all broadcasts for your account (including draft, scheduled, and already sent)
200
Response Schema: application/json
broadcastsrequired
» idrequired
» created_atrequired
» subjectrequired
» descriptionrequired
» contentrequired
» publicrequired
» published_atrequired
» send_atrequired
» thumbnail_altrequired
» thumbnail_urlrequired
» email_addressrequired
» preview_text
» email_templaterequired
»» idrequired
»» namerequired
» subscriber_filterrequired
»» allrequired
»»» typerequired
»»» ids
»» any
»»» typerequired
»»» idsrequired
»» none
»»» typerequired
»»» idsrequired
» publication_id
paginationrequired
» has_previous_pagerequired
» has_next_pagerequired
» start_cursorrequired
» end_cursorrequired
» per_pagerequired
Returns a 401 if the token and/or account cannot be authenticated
401
Response Schema: application/json
errorsrequired
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`."
]
}
Creates a new broadcast
201
Response Schema: application/json
broadcastrequired
» idrequired
» created_atrequired
» subjectrequired
» preview_textrequired
» descriptionrequired
» contentrequired
» publicrequired
» published_atrequired
» send_atrequired
» thumbnail_altrequired
» thumbnail_urlrequired
» email_addressrequired
» email_templaterequired
»» idrequired
»» namerequired
» subscriber_filterrequired
»» allrequired
»»» typerequired
»»» idsrequired
»» any
»»» typerequired
»»» idsrequired
»» none
»»» typerequired
»»» idsrequired
» publication_id
Returns a 401 if the token and/or account cannot be authenticated
401
Response Schema: application/json
errorsrequired
Returns a 403 with an error message if the current account is unauthorized to create a broadcast
403
Response Schema: application/json
errorsrequired
Returns a 422 with an error message when one or more of the parameters were invalid
422
Response Schema: application/json
errorsrequired
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."
]
}
Deletes the broadcast
204
Returns a 401 if the token and/or account cannot be authenticated
401
Response Schema: application/json
errorsrequired
Returns a 403 with an error message if the current account is unauthorized to update a broadcast
403
Response Schema: application/json
errorsrequired
Returns a 404 when the provided id does not exist
404
Response Schema: application/json
errorsrequired
Returns a 422 with an error message if the broadcast has already started sending or already sent
422
Response Schema: application/json
errorsrequired
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"
]
}
Returns the broadcast details
200
Response Schema: application/json
broadcastrequired
» idrequired
» created_atrequired
» subjectrequired
» descriptionrequired
» contentrequired
» publicrequired
» published_atrequired
» send_atrequired
» thumbnail_altrequired
» thumbnail_urlrequired
» email_addressrequired
» preview_text
» email_templaterequired
»» idrequired
»» namerequired
» subscriber_filterrequired
»» allrequired
»»» typerequired
»»» ids
»» any
»»» typerequired
»»» idsrequired
»» none
»»» typerequired
»»» idsrequired
» publication_id
Returns a 401 if the token and/or account cannot be authenticated
401
Response Schema: application/json
errorsrequired
Returns a 404 when the provided id does not exist
404
Response Schema: application/json
errorsrequired
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`."
]
}
Updates the broadcast and returns its details
200
Response Schema: application/json
broadcastrequired
» idrequired
» created_atrequired
» subjectrequired
» preview_textrequired
» descriptionrequired
» contentrequired
» publicrequired
» published_atrequired
» send_atrequired
» thumbnail_altrequired
» thumbnail_urlrequired
» email_addressrequired
» email_templaterequired
»» idrequired
»» namerequired
» subscriber_filterrequired
»» allrequired
»»» typerequired
»»» idsrequired
» publication_id
Returns a 401 if the token and/or account cannot be authenticated
401
Response Schema: application/json
errorsrequired
Returns a 403 with an error message if the current account is unauthorized to create a broadcast
403
Response Schema: application/json
errorsrequired
Returns a 404 when the provided id does not exist
404
Response Schema: application/json
errorsrequired
Returns a 422 with an error message when one or more of the parameters are invalid or the campaign has already started sending
422
Response Schema: application/json
errorsrequired
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"
]
}
Returns stats for a broadcast
200
Response Schema: application/json
broadcastrequired
» idrequired
» statsrequired
»» recipientsrequired
»» open_raterequired
»» click_raterequired
»» unsubscribesrequired
»» total_clicksrequired
»» show_total_clicksrequired
»» statusrequired
»» progressrequired
»» open_tracking_disabledrequired
»» click_tracking_disabledrequired
Returns a 401 if the token and/or account cannot be authenticated
401
Response Schema: application/json
errorsrequired
Returns a 404 when the provided id does not exist
404
Response Schema: application/json
errorsrequired
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"
]
}
Creates the custom_fields synchronously when 100 or less custom fields are requested
200
Response Schema: application/json
custom_fieldsrequired
» idrequired
» labelrequired
» keyrequired
» namerequired
» created_atrequired
failuresrequired
» custom_fieldrequired
»» idrequired
»» labelrequired
»» keyrequired
»» namerequired
»» created_atrequired
» errorsrequired
Creates or updates custom_fields asynchronously when more than 100 custom fields are requested
202
Response Schema: application/json
Returns a 401 if the token and/or account cannot be authenticated
401
Response Schema: application/json
errorsrequired
Returns a 413 when the size of the request would exceed the account's data limit for enqueued bulk requests
413
Response Schema: application/json
errorsrequired
Returns a 422 when
422
custom_fields
is empty or not an arrayResponse Schema: application/json
errorsrequired
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"
]
}
Returns a paginated list of all custom fields for your account
200
Response Schema: application/json
custom_fieldsrequired
» idrequired
» namerequired
» keyrequired
» labelrequired
paginationrequired
» has_previous_pagerequired
» has_next_pagerequired
» start_cursorrequired
» end_cursorrequired
» per_pagerequired
Returns a 401 if the token and/or account cannot be authenticated
401
Response Schema: application/json
errorsrequired
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"
]
}
Creates a new custom field and returns its details
201
Response Schema: application/json
custom_fieldrequired
» idrequired
» namerequired
» keyrequired
» labelrequired
Returns a 401 if the token and/or account cannot be authenticated
401
Response Schema: application/json
errorsrequired
Returns a 422 with an error message when the label is missing
422
Response Schema: application/json
errorsrequired
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."
]
}
Deletes the custom field
204
Returns a 401 if the token and/or account cannot be authenticated
401
Response Schema: application/json
errorsrequired
Returns a 404 when the provided id does not exist
404
Response Schema: application/json
errorsrequired
Returns a 422 when the custom field cannot be deleted
422
Response Schema: application/json
errorsrequired
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"
]
}
Updates the custom field and returns its details
200
Response Schema: application/json
custom_fieldrequired
» idrequired
» namerequired
» keyrequired
» labelrequired
Returns a 401 if the token and/or account cannot be authenticated
401
Response Schema: application/json
errorsrequired
Returns a 404 when the provided id does not exist
404
Response Schema: application/json
errorsrequired
Returns a 422 with an error mesage when one or more of the parameters are invalid
422
Response Schema: application/json
errorsrequired
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"
]
}
Adds subscribers to forms synchronously when 100 or less form/subscribers are requested
200
Response Schema: application/json
subscribersrequired
» idrequired
» first_namerequired
» email_addressrequired
» created_atrequired
» added_atrequired
» referrer_utm_parameters
»» sourcerequired
»» mediumrequired
»» campaignrequired
»» termrequired
»» contentrequired
» referrer
failuresrequired
Adds subscribers to forms asynchronously when more than 100 form/subscribers are requested
202
Response Schema: application/json
Returns a 401 if the token and/or account cannot be authenticated
401
Response Schema: application/json
errorsrequired
Returns a 413 when the size of the request would exceed the account's data limit for enqueued bulk requests
413
Response Schema: application/json
errorsrequired
Returns a 422 when
422
additions
is empty or not an arrayResponse Schema: application/json
errorsrequired
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"
]
}
Returns a paginated list of all forms and landing pages (embedded and hosted) for your account (including active and archived)
200
Response Schema: application/json
formsrequired
» idrequired
» namerequired
» created_atrequired
» typerequired
» formatrequired
» embed_jsrequired
» embed_urlrequired
» archivedrequired
» uidrequired
paginationrequired
» has_previous_pagerequired
» has_next_pagerequired
» start_cursorrequired
» end_cursorrequired
» per_pagerequired
Returns a 401 if the token and/or account cannot be authenticated
401
Response Schema: application/json
errorsrequired
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"
]
}
Returns a paginated list of subscribers for the specified form
200
Response Schema: application/json
subscribersrequired
» idrequired
» first_namerequired
» email_addressrequired
» staterequired
» created_atrequired
» added_atrequired
» fieldsrequired
»» categoryrequired
» referrer_utm_parameters
»» sourcerequired
»» mediumrequired
»» campaignrequired
»» termrequired
»» contentrequired
» referrer
paginationrequired
» has_previous_pagerequired
» has_next_pagerequired
» start_cursorrequired
» end_cursorrequired
» per_pagerequired
Returns a 401 if the token and/or account cannot be authenticated
401
Response Schema: application/json
errorsrequired
Returns a 404 when the provided id does not exist
404
Response Schema: application/json
errorsrequired
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"
]
}
Returns a 200 when the subscriber has already been added to the form
200
Response Schema: application/json
subscriberrequired
» idrequired
» first_namerequired
» email_addressrequired
» staterequired
» created_atrequired
» added_atrequired
» fieldsrequired
» referrer_utm_parameters
»» sourcerequired
»» mediumrequired
»» campaignrequired
»» termrequired
»» contentrequired
» referrer
Adds the subscriber to the form
201
Response Schema: application/json
subscriberrequired
» idrequired
» first_namerequired
» email_addressrequired
» staterequired
» created_atrequired
» added_atrequired
» fieldsrequired
» referrer_utm_parameters
»» sourcerequired
»» mediumrequired
»» campaignrequired
»» termrequired
»» contentrequired
» referrer
Returns a 401 if the token and/or account cannot be authenticated
401
Response Schema: application/json
errorsrequired
Returns a 404 when the provided id does not exist
404
Response Schema: application/json
errorsrequired
Returns a 422 with an error message when missing email address
422
Response Schema: application/json
errorsrequired
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"
]
}
Returns a 200 when the subscriber has already been added to the form
200
Response Schema: application/json
subscriberrequired
» idrequired
» first_namerequired
» email_addressrequired
» staterequired
» created_atrequired
» added_atrequired
» fieldsrequired
» referrer_utm_parameters
»» sourcerequired
»» mediumrequired
»» campaignrequired
»» termrequired
»» contentrequired
» referrer
Adds the subscriber to the form
201
Response Schema: application/json
subscriberrequired
» idrequired
» first_namerequired
» email_addressrequired
» staterequired
» created_atrequired
» added_atrequired
» fieldsrequired
» referrer_utm_parameters
»» sourcerequired
»» mediumrequired
»» campaignrequired
»» termrequired
»» contentrequired
» referrer
Returns a 401 if the token and/or account cannot be authenticated
401
Response Schema: application/json
errorsrequired
Returns a 404 when the provided id does not exist
404
Response Schema: application/json
errorsrequired
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"
]
}
Creates or updates the subscribers synchronously when 100 or less subscribers are requested
200
Response Schema: application/json
subscribersrequired
» idrequired
» first_namerequired
» email_addressrequired
» staterequired
» created_at
failuresrequired
» subscriberrequired
»» first_namerequired
»» email_addressrequired
»» staterequired
»» created_at
» errorsrequired
Creates or updates subscribers asynchronously when more than 100 subscribers are requested
202
Response Schema: application/json
Returns a 401 if the token and/or account cannot be authenticated
401
Response Schema: application/json
errorsrequired
Returns a 403 when the number of subscribers in the request would exceed the account's subscriber limit
403
Response Schema: application/json
errorsrequired
Returns a 413 when the size of the request would exceed the account's data limit for enqueued bulk requests
413
Response Schema: application/json
errorsrequired
Returns a 422 when
422
subscribers
is empty or not an arrayResponse Schema: application/json
errorsrequired
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`"
]
}
Returns a list of subscribers matching the sort and filter params, defaulting to active subscribers sorted in descending order by id
200
Response Schema: application/json
subscribersrequired
» idrequired
» first_namerequired
» email_addressrequired
» staterequired
» created_atrequired
» fieldsrequired
»» categoryrequired
paginationrequired
» has_previous_pagerequired
» has_next_pagerequired
» start_cursorrequired
» end_cursorrequired
» per_pagerequired
Returns a 401 if the token and/or account cannot be authenticated
401
Response Schema: application/json
errorsrequired
raises an error when sorting on cancelled_at without the cancelled status
422
Response Schema: application/json
errorsrequired
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"
]
}
Returns a 200 and updates the subscriber first name when a subscriber with provided email already exists
200
Response Schema: application/json
subscriberrequired
» idrequired
» first_namerequired
» email_addressrequired
» staterequired
» created_atrequired
» fieldsrequired
Creates a new subscriber
201
Response Schema: application/json
subscriberrequired
» idrequired
» first_namerequired
» email_addressrequired
» staterequired
» created_atrequired
» fieldsrequired
Returns a 202 and asynchronously adds custom fields for the new subscriber when more than 10 custom fields are included in the request
202
Response Schema: application/json
subscriberrequired
» idrequired
» first_namerequired
» email_addressrequired
» staterequired
» created_atrequired
» fieldsrequired
Returns a 401 if the token and/or account cannot be authenticated
401
Response Schema: application/json
errorsrequired
Returns a 422 with an error message when one or more of the parameters are invalid
422
Response Schema: application/json
errorsrequired
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"
]
}
Returns the subscriber details
200
Response Schema: application/json
subscriberrequired
» idrequired
» first_namerequired
» email_addressrequired
» staterequired
» created_atrequired
» fieldsrequired
»» categoryrequired
Returns a 401 if the token and/or account cannot be authenticated
401
Response Schema: application/json
errorsrequired
Returns a 404 when the provided id does not exist
404
Response Schema: application/json
errorsrequired
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"
]
}
Updates the subscriber's email address and first name
200
Response Schema: application/json
subscriberrequired
» idrequired
» first_namerequired
» email_addressrequired
» staterequired
» created_atrequired
» fieldsrequired
Returns a 202 and asynchronously updates custom fields for the subscriber when more than 10 custom fields are included in the request
202
Response Schema: application/json
subscriberrequired
» idrequired
» first_namerequired
» email_addressrequired
» staterequired
» created_atrequired
» fieldsrequired
Returns a 401 if the token and/or account cannot be authenticated
401
Response Schema: application/json
errorsrequired
Returns a 404 when the provided id does not exist
404
Response Schema: application/json
errorsrequired
Returns 422 with an error when email address is already in use
422
Response Schema: application/json
errorsrequired
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"
]
}
Unsubscribes the subscriber
204
Returns a 401 if the token and/or account cannot be authenticated
401
Response Schema: application/json
errorsrequired
Returns a 404 when the provided id does not exist
404
Response Schema: application/json
errorsrequired
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"
]
}
Returns a paginated list of all tags for a subscriber
200
Response Schema: application/json
tagsrequired
» idrequired
» namerequired
» added_at
» tagged_at
pagination
» has_previous_pagerequired
» has_next_pagerequired
» start_cursorrequired
» end_cursorrequired
» per_pagerequired
Returns a 401 if the token and/or account cannot be authenticated
401
Response Schema: application/json
errorsrequired
Returns a 404 when the provided id does not exist
404
Response Schema: application/json
errorsrequired
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"
]
}
Creates the tags synchronously when 100 or less tags are requested
200
Response Schema: application/json
tagsrequired
» idrequired
» namerequired
» created_atrequired
failuresrequired
» tagrequired
»» idrequired
»» namerequired
»» created_atrequired
» errorsrequired
Creates or updates tags asynchronously when more than 100 tags are requested
202
Response Schema: application/json
Returns a 401 if the token and/or account cannot be authenticated
401
Response Schema: application/json
errorsrequired
Returns a 413 when the size of the request would exceed the account's data limit for enqueued bulk requests
413
Response Schema: application/json
errorsrequired
Returns a 422 when
422
tags
is empty or not an arrayResponse Schema: application/json
errorsrequired
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"
]
}
Deletes the taggings synchronously when 100 or less tags/subscribers are provided
200
Response Schema: application/json
failuresrequired
Destroys taggings asynchronously when more than 100 tags/subscribers are provided
202
Response Schema: application/json
Returns a 401 if the token and/or account cannot be authenticated
401
Response Schema: application/json
errorsrequired
Returns a 413 when the size of the request would exceed the account's data limit for enqueued bulk requests
413
Response Schema: application/json
errorsrequired
Returns a 422 when
422
taggings
is empty or not an arrayResponse Schema: application/json
errorsrequired
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"
]
}
Creates the taggings synchronously when 100 or less tags/subscribers are requested
200
Response Schema: application/json
subscribersrequired
» idrequired
» first_namerequired
» email_addressrequired
» created_atrequired
» tagged_atrequired
failuresrequired
Creates or updates taggings asynchronously when more than 100 tags/subscribers are requested
202
Response Schema: application/json
Returns a 401 if the token and/or account cannot be authenticated
401
Response Schema: application/json
errorsrequired
Returns a 413 when the size of the request would exceed the account's data limit for enqueued bulk requests
413
Response Schema: application/json
errorsrequired
Returns a 422 when
422
taggings
is empty or not an arrayResponse Schema: application/json
errorsrequired
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"
]
}
Returns a paginated list of all tags for your account
200
Response Schema: application/json
tagsrequired
» idrequired
» namerequired
» created_atrequired
paginationrequired
» has_previous_pagerequired
» has_next_pagerequired
» start_cursorrequired
» end_cursorrequired
» per_pagerequired
Returns a 401 if the token and/or account cannot be authenticated
401
Response Schema: application/json
errorsrequired
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"
]
}
Creates the tag
201
Response Schema: application/json
tagrequired
» idrequired
» namerequired
» created_atrequired
Returns a 401 if the token and/or account cannot be authenticated
401
Response Schema: application/json
errorsrequired
Returns a 422 with an error message when the tag already exists
422
Response Schema: application/json
errorsrequired
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"
]
}
Updates the tag name
200
Response Schema: application/json
tagrequired
» idrequired
» namerequired
» created_atrequired
Returns a 401 if the token and/or account cannot be authenticated
401
Response Schema: application/json
errorsrequired
Returns a 404 when the provided id does not exist
404
Response Schema: application/json
errorsrequired
Returns a 422 with an error message when name is invalid
422
Response Schema: application/json
errorsrequired
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"
]
}
Removes the tag from the subscriber
204
Returns a 401 if the token and/or account cannot be authenticated
401
Response Schema: application/json
errorsrequired
Returns a 404 when the provided id does not exist
404
Response Schema: application/json
errorsrequired
Returns a 422 with an error message when missing email address
422
Response Schema: application/json
errorsrequired
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"
]
}
Returns a paginated list of subscribers for the specified tag
200
Response Schema: application/json
subscribersrequired
» idrequired
» first_namerequired
» email_addressrequired
» staterequired
» created_atrequired
» tagged_atrequired
» fieldsrequired
»» categoryrequired
paginationrequired
» has_previous_pagerequired
» has_next_pagerequired
» start_cursorrequired
» end_cursorrequired
» per_pagerequired
Returns a 401 if the token and/or account cannot be authenticated
401
Response Schema: application/json
errorsrequired
Returns a 404 when the provided id does not exist
404
Response Schema: application/json
errorsrequired
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"
]
}
Returns a 200 when the subscriber already has the tag
200
Response Schema: application/json
subscriberrequired
» idrequired
» first_namerequired
» email_addressrequired
» staterequired
» created_atrequired
» tagged_atrequired
» fieldsrequired
Tags the subscriber
201
Response Schema: application/json
subscriberrequired
» idrequired
» first_namerequired
» email_addressrequired
» staterequired
» created_atrequired