A reference guide for building AI agents: every method, how to authenticate, and the permissions each one needs.
The Klaviyo API is how an app or AI agent works with a Klaviyo account: reading and creating customer profiles, building lists and segments, tracking events, and sending email and text campaigns through flows. Access is granted through a private API key or an OAuth grant, and a set of scopes sets which areas a call can read or write, like profiles:read or campaigns:write. Klaviyo dates each version of its API, and a state change can be pushed to a registered endpoint as it happens.
How an app or AI agent connects to Klaviyo determines what it can reach. There is a route for making calls, a route for receiving events as they happen, and a hosted server that exposes Klaviyo tools to agents, and each is governed by the key or grant behind it and the scopes it carries.
The REST API uses the JSON:API format, takes and returns typed JSON objects with attributes and relationships, and pages lists with a cursor, at https://a.klaviyo.com/api. A call authenticates with a private API key in an Authorization header or with an OAuth token, and names a dated version in the revision header. A separate client API at https://a.klaviyo.com/client supports public-key calls from a browser or mobile app.
Klaviyo POSTs events to an HTTPS endpoint registered through the Webhooks API and subscribed to topics, like an email being clicked or a text message being received. Events are batched, up to 1,000 per request, and Klaviyo sends up to 10 concurrent requests per account. Topics are gated by both the webhooks scope and the scope for the underlying data.
A first-party Model Context Protocol server exposes Klaviyo tools to AI clients across profiles, campaigns, flows, lists, segments, events, metrics, and templates. It is generally available. A hosted remote server at https://mcp.klaviyo.com/mcp authenticates with OAuth and dynamic client registration; a local server, run with uvx klaviyo-mcp-server, authenticates with a private API key and its scopes.
A private API key calls the API for a single account that owns it. It is sent in an Authorization header as Klaviyo-API-Key followed by the key, and a key can be scoped to specific areas when it is created. A private key must never be exposed in client code.
OAuth uses the standard authorization-code flow. A tech partner's app requests a space-separated list of scopes, the account owner approves them, and the app exchanges the code for an access token tied to that account. Each account grants and revokes access on its own, so no long-lived key is shared.
A public API key, the account's six-character site ID, is safe to use in a browser or mobile app. It is limited to the client endpoints, like creating an event or subscribing a profile, and cannot read account data.
The Klaviyo API is split into areas an agent can act on, like profiles, lists, segments, events, campaigns, flows, metrics, and templates. Each area has its own methods and its own scope, and a write in some areas changes who is subscribed or sends marketing messages.
Methods for reading and writing customer profiles.
Methods for working with lists and their membership.
Methods for working with segments.
Methods for tracking and reading events.
Methods for working with email, SMS, and push campaigns.
Methods for reading automated flows.
Methods for reading metrics and aggregating event data.
Methods for working with message templates.
Methods for subscribing and unsubscribing profiles to marketing.
Filter by method, access, or permission, or search any path. Select a row for version detail, rate limits, the related webhook event, and the source.
| Method | Endpoint | What it does | Access | Permission | Version | |
|---|---|---|---|---|---|---|
ProfilesMethods for reading and writing customer profiles.5 | ||||||
| GET | /api/profiles | List profiles in the account, with filtering, sorting, and sparse fields. | read | profiles:read | Current | |
Read-only. Adding additional-fields[profile]=predictive_analytics lowers the tier to 10/s burst, 150/m steady. Acts onprofile Permission (capability) profiles:readVersionAvailable since the API’s base version Webhook eventNone Rate limit75/s burst, 750/m steady (L) SourceOfficial documentation ↗ | ||||||
| GET | /api/profiles/{id} | Retrieve a single profile by id. | read | profiles:read | Current | |
Read-only. Acts onprofile Permission (capability) profiles:readVersionAvailable since the API’s base version Webhook eventNone Rate limit75/s burst, 750/m steady (L) SourceOfficial documentation ↗ | ||||||
| POST | /api/profiles | Create a new profile with attributes like email, phone, and properties. | write | profiles:write | Current | |
Body limited to 100KB. Acts onprofile Permission (capability) profiles:writeVersionAvailable since the API’s base version Webhook eventNone Rate limit75/s burst, 750/m steady (L) SourceOfficial documentation ↗ | ||||||
| PATCH | /api/profiles/{id} | Update an existing profile's attributes or properties. | write | profiles:write | Current | |
A core write. Acts onprofile Permission (capability) profiles:writeVersionAvailable since the API’s base version Webhook eventNone Rate limit75/s burst, 750/m steady (L) SourceOfficial documentation ↗ | ||||||
| POST | /api/profile-import | Create a profile or update it if one already matches, in a single call. | write | profiles:write | Current | |
Upsert by identifier. Body limited to 100KB. Acts onprofile Permission (capability) profiles:writeVersionAvailable since the API’s base version Webhook eventNone Rate limit75/s burst, 750/m steady (L) SourceOfficial documentation ↗ | ||||||
ListsMethods for working with lists and their membership.3 | ||||||
| GET | /api/lists | List the account's lists. | read | lists:read | Current | |
Read-only. Acts onlist Permission (capability) lists:readVersionAvailable since the API’s base version Webhook eventNone Rate limit75/s burst, 750/m steady (L) SourceOfficial documentation ↗ | ||||||
| POST | /api/lists | Create a new list. | write | lists:write | Current | |
A core write. Acts onlist Permission (capability) lists:writeVersionAvailable since the API’s base version Webhook eventNone Rate limit75/s burst, 750/m steady (L) SourceOfficial documentation ↗ | ||||||
| POST | /api/lists/{id}/relationships/profiles | Add one or more profiles to a list. | write | lists:write | Current | |
Needs lists:write and profiles:write. Adds membership; does not change marketing consent on its own. Up to 1,000 profiles per request. Acts onlist Permission (capability) lists:writeVersionAvailable since the API’s base version Webhook eventNone Rate limit75/s burst, 750/m steady (L) SourceOfficial documentation ↗ | ||||||
SegmentsMethods for working with segments.2 | ||||||
| GET | /api/segments | List the account's segments. | read | segments:read | Current | |
Read-only. Acts onsegment Permission (capability) segments:readVersionAvailable since the API’s base version Webhook eventNone Rate limit75/s burst, 750/m steady (L) SourceOfficial documentation ↗ | ||||||
| GET | /api/segments/{id} | Retrieve a single segment by id. | read | segments:read | Current | |
Read-only. Acts onsegment Permission (capability) segments:readVersionAvailable since the API’s base version Webhook eventNone Rate limit75/s burst, 750/m steady (L) SourceOfficial documentation ↗ | ||||||
EventsMethods for tracking and reading events.2 | ||||||
| GET | /api/events | List events recorded in the account, with filtering by metric and profile. | read | events:read | Current | |
Read-only. Acts onevent Permission (capability) events:readVersionAvailable since the API’s base version Webhook eventNone Rate limit350/s burst, 3500/m steady (XL) SourceOfficial documentation ↗ | ||||||
| POST | /api/events | Record a new event against a profile, creating or updating the profile if needed. | write | events:write | Current | |
Can create or update profile properties as a side effect. Acts onevent Permission (capability) events:writeVersionAvailable since the API’s base version Webhook eventNone Rate limit350/s burst, 3500/m steady (XL) SourceOfficial documentation ↗ | ||||||
CampaignsMethods for working with email, SMS, and push campaigns.3 | ||||||
| GET | /api/campaigns | List campaigns. A channel filter on messages.channel is required. | read | campaigns:read | Current | |
Requires a filter such as equals(messages.channel,'email'), 'sms', or 'mobile_push'. Acts oncampaign Permission (capability) campaigns:readVersionAvailable since the API’s base version Webhook eventNone Rate limit10/s burst, 150/m steady (M) SourceOfficial documentation ↗ | ||||||
| POST | /api/campaigns | Create a campaign for email, SMS, or push. | write | campaigns:write | Current | |
Creates the campaign; sending is a separate send-job call. Acts oncampaign Permission (capability) campaigns:writeVersionAvailable since the API’s base version Webhook event sent_smsRate limit10/s burst, 150/m steady (M) SourceOfficial documentation ↗ | ||||||
| POST | /api/campaign-send-jobs | Trigger a campaign to send by creating a campaign send job. | write | campaigns:write | Current | |
Sends real marketing messages to the campaign's audience. Acts oncampaign-send-job Permission (capability) campaigns:writeVersionAvailable since the API’s base version Webhook eventNone Rate limit10/s burst, 150/m steady (M) SourceOfficial documentation ↗ | ||||||
FlowsMethods for reading automated flows.2 | ||||||
| GET | /api/flows | List automated flows in the account. | read | flows:read | Current | |
Read-only. Acts onflow Permission (capability) flows:readVersionAvailable since the API’s base version Webhook eventNone Rate limit3/s burst, 60/m steady (S) SourceOfficial documentation ↗ | ||||||
| GET | /api/flows/{id} | Retrieve a single flow by id. | read | flows:read | Current | |
Read-only. Acts onflow Permission (capability) flows:readVersionAvailable since the API’s base version Webhook eventNone Rate limit3/s burst, 60/m steady (S) SourceOfficial documentation ↗ | ||||||
Metrics & ReportingMethods for reading metrics and aggregating event data.2 | ||||||
| GET | /api/metrics | List metrics in the account, like Placed Order or Opened Email. | read | metrics:read | Current | |
Read-only. Acts onmetric Permission (capability) metrics:readVersionAvailable since the API’s base version Webhook eventNone Rate limit10/s burst, 150/m steady (M) SourceOfficial documentation ↗ | ||||||
| POST | /api/metric-aggregates | Query and aggregate the event data behind a metric over time. | read | metrics:read | Current | |
A POST used to read aggregated data; no data is changed. Acts onmetric-aggregate Permission (capability) metrics:readVersionAvailable since the API’s base version Webhook eventNone Rate limit3/s burst, 60/m steady (S) SourceOfficial documentation ↗ | ||||||
TemplatesMethods for working with message templates.2 | ||||||
| GET | /api/templates | List message templates in the account. | read | templates:read | Current | |
Read-only. Acts ontemplate Permission (capability) templates:readVersionAvailable since the API’s base version Webhook eventNone Rate limit75/s burst, 750/m steady (L) SourceOfficial documentation ↗ | ||||||
| POST | /api/templates | Create a new message template. | write | templates:write | Current | |
A core write. Acts ontemplate Permission (capability) templates:writeVersionAvailable since the API’s base version Webhook eventNone Rate limit75/s burst, 750/m steady (L) SourceOfficial documentation ↗ | ||||||
SubscriptionsMethods for subscribing and unsubscribing profiles to marketing.2 | ||||||
| POST | /api/profile-subscription-bulk-create-jobs | Subscribe one or more profiles to email, SMS, WhatsApp, or push marketing. | write | subscriptions:write | Current | |
Also accepted with lists:write or profiles:write. Up to 1,000 profiles per request; records marketing consent. Acts onprofile-subscription-bulk-create-job Permission (capability) subscriptions:writeVersionAvailable since the API’s base version Webhook eventNone Rate limit75/s burst, 750/m steady (L) SourceOfficial documentation ↗ | ||||||
| POST | /api/profile-subscription-bulk-delete-jobs | Unsubscribe one or more profiles from marketing. | write | subscriptions:write | Current | |
Also accepted with lists:write or profiles:write. Up to 1,000 profiles per request; removes marketing consent. Acts onprofile-subscription-bulk-delete-job Permission (capability) subscriptions:writeVersionAvailable since the API’s base version Webhook eventNone Rate limit75/s burst, 750/m steady (L) SourceOfficial documentation ↗ | ||||||
Klaviyo can notify an app when something happens in an account, like an email being clicked or a text message being received. A webhook subscribes to a set of topics and Klaviyo POSTs batched events to the registered endpoint, so an integration learns about activity without polling.
| Event | What it signals | Triggered by |
|---|---|---|
event:klaviyo.sent_sms | A text message was sent to a profile. Subscribing to this topic also requires the scope for the underlying event data. | /api/campaigns |
event:klaviyo.received_sms | A text message was received from a profile, like an inbound reply. Subscribing to this topic also requires the scope for the underlying event data. | In-app only |
Klaviyo limits how fast an app can call, with a per-second burst limit and a per-minute steady limit applied per account, and each method is placed in a rate-limit tier that sets both numbers.
Klaviyo meters requests per account with two windows at once, a per-second burst limit and a per-minute steady limit, and returns HTTP 429 when either is crossed. Each method sits in a named tier that sets both numbers, from XS (1/s burst, 15/m steady) through S, M, L, and up to XL (350/s burst, 3500/m steady). Most read and write endpoints sit at L (75/s, 750/m); reporting and aggregate queries sit lower, and event creation sits at XL. A normal response carries RateLimit-Limit, RateLimit-Remaining, and RateLimit-Reset headers; a 429 replaces them with Retry-After, the seconds to wait before retrying. Per-method tiers are shown on each row.
Lists are cursor-based. A response includes a links object with next and prev cursors, and page[cursor] fetches the following page while page[size] sets the page size. The maximum page size varies by endpoint, commonly 10, 50, or 100, and some endpoints fix it. Results are not offset-paginated, so a client follows the next cursor until it is absent.
Page size maximums vary per endpoint and are stated on each reference page. A profile create or update accepts a body up to 100KB. Bulk subscribe and unsubscribe jobs accept up to 1,000 profiles per request, and an outbound webhook batch can carry up to 1,000 events.
The status codes an agent should handle, and what to do about each.
| Status | Code | Meaning | What to do |
|---|---|---|---|
| 400 | invalid_request | The request was malformed or missing required input, or the API key is missing or invalid. | Read the error detail, fix the body, parameters, or Authorization header, and resend. The request is not retryable as-is. |
| 401 | not_authenticated | Authentication credentials were missing or could not be verified. | Send a valid private API key or OAuth token in the Authorization header. |
| 403 | not_authorized | The credentials are valid but lack the scope this request needs, like calling a write endpoint with a read-only scope. | Grant the missing scope on the key or re-authorize the OAuth app with the needed scope. |
| 404 | not_found | The requested resource does not exist or is not visible to these credentials. | Verify the resource id and that it belongs to the authenticated account. |
| 409 | conflict | The request conflicts with the current state of the resource, like a duplicate or a concurrent change. | Re-fetch the resource, reconcile the change, and retry. |
| 429 | throttled | A burst or steady rate limit was exceeded for the account. | Wait the number of seconds in the Retry-After header, then retry with backoff and a smoother request rate. |
| 500 | server_error | An error on Klaviyo's side. It is rare. | Retry with backoff, and contact Klaviyo support if it persists. |
Klaviyo versions its API by date. A request names a revision in a header, and a revision stays stable for a year before a year of deprecation, so an integration upgrades on a schedule rather than all at once.
Klaviyo dates each revision and a request names one in the revision header. A revision is stable for a year, then deprecated for a year before it retires.
A backward-compatible dated revision.
A backward-compatible dated revision.
A backward-compatible dated revision.
A dated revision that introduced a breaking change to subscription endpoints.
Pin a revision in the header and move up before it retires.
Klaviyo API changelog ↗Bollard AI sits between a team's AI agents and Klaviyo. Grant each agent exactly the access it needs, read or write, area by area, and every call is checked and logged.