# Klaviyo

Klaviyo is an email marketing and automation platform designed for e-commerce businesses. It provides tools for managing customer profiles, email campaigns, automated flows, audience segmentation, and analytics. The Sling Klaviyo connector extracts data from the Klaviyo API (v2025-07-15), supporting profiles, lists, segments, campaigns, flows, events, metrics, templates, tags, catalog items, and membership data.

{% hint style="success" %}
**CLI Pro Required**: APIs require a [CLI Pro token](https://docs.slingdata.io/sling-cli/cli-pro) or [Platform Plan](https://docs.slingdata.io/sling-platform/platform).
{% endhint %}

## Setup

The following credentials are accepted:

**Secrets:**

* `api_key` **(required)** -> Your Klaviyo Private API Key

### Getting Your API Key

1. Log in to your [Klaviyo account](https://www.klaviyo.com/login)
2. Click **Settings** (gear icon) in the bottom-left corner
3. Go to **Account** > **Settings** > **API Keys**
4. Click **Create Private API Key**
5. Give it a name (e.g., "Sling Integration")
6. Select **Read-Only Key** for the access level (Sling only needs read access)
7. Click **Create** and copy the key (it starts with `pk_`)

{% hint style="warning" %}
**Important:** Use a **Private API Key** (starts with `pk_`), not a Public API Key (6-character alphanumeric string). Public keys do not have access to the server-side API endpoints that Sling uses.
{% endhint %}

### Using `sling conns`

{% code overflow="wrap" %}

```bash
sling conns set KLAVIYO type=api spec=klaviyo secrets='{ api_key: "pk_xxxxxxxxxxxxxxxxxxxx" }'
```

{% endcode %}

### Environment Variable

See [here](https://docs.slingdata.io/sling-cli/environment#dot-env-file-.env.sling) to learn more about the `.env.sling` file.

{% code overflow="wrap" %}

```bash
export KLAVIYO='{ type: api, spec: klaviyo, secrets: { api_key: "pk_xxxxxxxxxxxxxxxxxxxx" } }'
```

{% endcode %}

### Sling Env File YAML

See [here](https://docs.slingdata.io/sling-cli/environment#sling-env-file-env.yaml) to learn more about the sling `env.yaml` file.

```yaml
connections:
  KLAVIYO:
    type: api
    spec: klaviyo
    secrets:
      api_key: "pk_xxxxxxxxxxxxxxxxxxxx"
```

## Replication

Here's an example replication configuration to sync Klaviyo data to a PostgreSQL database:

```yaml
source: KLAVIYO
target: MY_POSTGRES

defaults:
  mode: full-refresh
  object: klaviyo.{stream_name}

streams:
  # Core data with incremental sync
  profiles:
    mode: incremental
  events:
    mode: incremental

  # Campaign and automation data
  campaigns:
  flows:
  templates:
    mode: incremental

  # Audience data
  lists:
  segments:

  # Reference data
  metrics:
  tags:
  catalog_items:

  # Membership data (parent-child)
  list_profiles:
  segment_profiles:
```

**Incremental sync example:**

```yaml
source: KLAVIYO
target: MY_POSTGRES

defaults:
  mode: incremental
  object: klaviyo.{stream_name}

streams:
  profiles:
  events:
  templates:
```

**Full refresh example:**

```yaml
source: KLAVIYO
target: MY_POSTGRES

defaults:
  mode: full-refresh
  object: klaviyo.{stream_name}

streams:
  lists:
  segments:
  campaigns:
  flows:
  metrics:
  tags:
  catalog_items:
```

## Endpoints

### Audience Management

| Endpoint           | Description                                         | Incremental |
| ------------------ | --------------------------------------------------- | ----------- |
| `profiles`         | Customer profiles (contacts/subscribers)            | Yes         |
| `lists`            | Email lists/audiences                               | No          |
| `segments`         | Audience segments                                   | No          |
| `list_profiles`    | Profile memberships per list (child of lists)       | No          |
| `segment_profiles` | Profile memberships per segment (child of segments) | No          |

### Campaign & Automation

| Endpoint    | Description                  | Incremental |
| ----------- | ---------------------------- | ----------- |
| `campaigns` | Email campaigns              | No          |
| `flows`     | Automation workflows (flows) | No          |
| `templates` | Email templates              | Yes         |

### Analytics & Events

| Endpoint  | Description                                          | Incremental |
| --------- | ---------------------------------------------------- | ----------- |
| `events`  | Email activity events (opens, clicks, bounces, etc.) | Yes         |
| `metrics` | Metric/event type definitions                        | No          |

### Catalog & Metadata

| Endpoint        | Description                   | Incremental |
| --------------- | ----------------------------- | ----------- |
| `tags`          | Tags for organizing resources | No          |
| `catalog_items` | Product catalog items         | No          |

To discover available endpoints:

```bash
sling conns discover KLAVIYO
```

## Parent-Child Endpoints

Some endpoints are children of parent endpoints and require the parent to run first:

* **list\_profiles** -> Requires `lists` to run first (iterates through each list to fetch member profiles)
* **segment\_profiles** -> Requires `segments` to run first (iterates through each segment to fetch member profiles)

When using these endpoints in a replication, Sling automatically handles the ordering via internal queues. The parent endpoint collects IDs, and the child endpoint iterates through them.

## Incremental Sync

The Klaviyo connector supports time-based incremental sync for the following endpoints:

* **profiles** - Syncs profiles modified after the last sync using the `updated` field
* **events** - Syncs events created after the last sync using the `datetime` field
* **templates** - Syncs templates modified after the last sync using the `updated` field

### How it works

* **First run:** Fetches records from the last 30 days (profiles and events) or last 365 days (templates)
* **Subsequent runs:** Only fetches records created or modified after the last sync timestamp
* **Profiles** use `greater-than` filter on the `updated` field
* **Events** and **templates** use `greater-or-equal` filter on their respective date fields

## Rate Limiting

The Klaviyo API enforces rate limits based on your account plan:

* **Free:** 3 requests/second for most endpoints
* **Paid plans:** Higher limits available

The connector automatically:

* Uses conservative rate limiting (3 requests/second)
* Limits concurrency to 3 parallel requests
* Retries with exponential backoff on 429 (rate limit) responses (up to 5 attempts)

## Common Use Cases

### Sync Customer Profiles and Activity

```yaml
source: KLAVIYO
target: MY_POSTGRES

defaults:
  mode: incremental
  object: klaviyo.{stream_name}

streams:
  profiles:
  events:
  metrics:
    mode: full-refresh
```

### Sync Campaign and Automation Data

```yaml
source: KLAVIYO
target: MY_POSTGRES

defaults:
  mode: full-refresh
  object: klaviyo.{stream_name}

streams:
  campaigns:
  flows:
  templates:
    mode: incremental
```

### Sync Audience Membership Data

```yaml
source: KLAVIYO
target: MY_POSTGRES

defaults:
  mode: full-refresh
  object: klaviyo.{stream_name}

streams:
  lists:
  segments:
  list_profiles:
  segment_profiles:
```

### Sync All Klaviyo Data

```yaml
source: KLAVIYO
target: MY_POSTGRES

defaults:
  mode: full-refresh
  object: klaviyo.{stream_name}

streams:
  '*':

  # Override incremental endpoints
  profiles:
    mode: incremental
  events:
    mode: incremental
  templates:
    mode: incremental
```

If you are facing issues connecting, please reach out to us at <support@slingdata.io>, on [discord](https://discord.gg/q5xtaSNDvp) or open a Github Issue [here](https://github.com/slingdata-io/sling-cli/issues).


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.slingdata.io/connections/api-connections/klaviyo.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
