> ## Documentation Index
> Fetch the complete documentation index at: https://docs.corsair.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Kit plugin

> Email marketing with Kit (formerly ConvertKit) - manage subscribers, tags, custom fields and forms, subscribe an address through a form, unsubscribe a subscriber, and read the account with its plan and sending addresses.

Use **Kit** through Corsair: one client, typed API calls.

Create a key in Kit under Settings, Developer, API Keys. It is sent in the `X-Kit-Api-Key` header, not as a Bearer token; that header is the OAuth path and a key sent that way is refused.

Things to know before you call:

* **Kit pages by cursor.** A list answers a `pagination` block with `end_cursor`, `start_cursor` and `has_next_page`. Pass `end_cursor` back as `after` for the next page, or `start_cursor` as `before` for the previous one, and stop when `has_next_page` is false.
* **Only active subscribers are returned by default.** `subscribers.list` takes `status`; pass `all` to widen it, or one of `active`, `inactive`, `bounced`, `complained`, `cancelled`.
* **`canceled_at` needs the cancelled status.** Asking for it beside any other status is refused, and the plugin checks that before the call rather than letting Kit answer 422.
* **Creating a subscriber with an address already on the list returns the existing one**, so a create is safe to repeat.
* **Custom field values go by `key`, not label.** A subscriber's `fields` map is keyed by the field's `key`, such as `last_name`. An unknown key is ignored and named in the response `warnings` array rather than failing, so read `warnings` when a value seems missing.
* **Tag and form subscribes need an existing subscriber.** `tags.tagSubscriber` and `forms.subscribe` find the subscriber by address and answer 404 when there is none, so call `subscribers.create` first for a new address. Subscribing through a form then applies the form's incentive and records `added_at`.
* **No bulk routes.** Kit only accepts its `/v4/bulk/*` routes with an OAuth token, and this plugin authenticates with an API key, so create subscribers one at a time with `subscribers.create`.
* **`subscribers.unsubscribe` cannot be undone from here.** It stops every future send to that person, and only they can resubscribe.
* **Rate limits.** Kit enforces two request windows and sends `Retry-After` on a 429, which the plugin honours before backing off.
* **Webhooks.** The plugin does not receive Kit webhooks; Kit has a separate endpoint-management API that is not wrapped here.

**What you get:**

* 16 typed API operations

## Setup

**1. Install**

```bash npm theme={null}
npm install corsair @corsair-dev/kit better-sqlite3
npm install --save-dev @types/better-sqlite3
```

```bash yarn theme={null}
yarn add corsair @corsair-dev/kit better-sqlite3
yarn add --dev @types/better-sqlite3
```

```bash pnpm theme={null}
pnpm install corsair @corsair-dev/kit better-sqlite3
pnpm install --save-dev @types/better-sqlite3
```

```bash bun theme={null}
bun add corsair @corsair-dev/kit better-sqlite3
bun add --dev @types/better-sqlite3
```

**2. Add the plugin**

```ts corsair.ts theme={null}
import Database from 'better-sqlite3';
import { createCorsair } from 'corsair';
import { kit } from '@corsair-dev/kit';

export const corsair = createCorsair({
	plugins: [
		kit(),
	],
	database: new Database('corsair.db'),
	kek: process.env.CORSAIR_KEK!,
	multiTenancy: true,
	hub: {
		projectApiKey: process.env.CORSAIR_API_KEY!,
		signingSecret: process.env.CORSAIR_SIGNING_SECRET!,
	},
});
```

With `multiTenancy: true`, scope calls with `corsair.withTenant(id)`. See [Quick start](https://docs.corsair.dev/quick-start.md) for KEK + Hub keys, and [Multi-tenancy](https://docs.corsair.dev/concepts/multi-tenancy.md) for account isolation.

**3. Choose authentication**

> [tab] API Key (Recommended)
>
> Store the Kit API key before the first call: `pnpm corsair setup --plugin=kit --tenant=acme api_key=<your-key>` (leave out `--tenant` without `multiTenancy`), or pass it as `key` in the plugin options. With Hub, each tenant enters their own key on the connect page. See [API key auth](https://docs.corsair.dev/concepts/api-key).
>
> ```ts theme={null}
> kit()
> ```
>
> More: [API Key](https://docs.corsair.dev/concepts/api-key)

**4. Connect a tenant**

Mint a connect link and send the tenant to it. Hub hosts the page and delivers the result to your app — see [Connect / OAuth](https://docs.corsair.dev/management/connect).

```ts theme={null}
const { connectUrl } = await corsair.manage.connect.createLink({
	plugin: 'kit',
	tenantId: 'acme',
});
// redirect the user's browser to connectUrl
```

## Example API calls

**List the first page of active subscribers**

```ts theme={null}
const tenant = corsair.withTenant('acme');
await tenant.kit.api.subscribers.list({ per_page: 25 });
```

**Add a subscriber**

```ts theme={null}
const tenant = corsair.withTenant('acme');
await tenant.kit.api.subscribers.create({ email_address: 'jordan@acme.example', first_name: 'Jordan' });
```

See the full list on the [API](https://docs.corsair.dev/plugins/kit/api.md) page.

## What's next

> [card] [API reference](https://docs.corsair.dev/plugins/kit/api.md)
>
> Every `kit.api.*` operation with input and output types.

> [card] [Connect / OAuth](https://docs.corsair.dev/management/connect)
>
> createLink, Hub delivery, and tenant connect flows.

> [card] [Use with agents](https://docs.corsair.dev/mcp-adapters/mcp-adapters)
>
> Expose this plugin's operations as MCP tools.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.