klaviyo

Klaviyo API integration with managed OAuth. Access profiles, lists, segments, campaigns, flows, events, metrics, templates, catalogs, and webhooks. Use this skill when users want to manage email marketing, customer data, or integrate with Klaviyo workflows. For other third party apps, use the api-gateway skill (https://clawhub.ai/byungkyu/api-gateway).

7 stars

Best use case

klaviyo is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Klaviyo API integration with managed OAuth. Access profiles, lists, segments, campaigns, flows, events, metrics, templates, catalogs, and webhooks. Use this skill when users want to manage email marketing, customer data, or integrate with Klaviyo workflows. For other third party apps, use the api-gateway skill (https://clawhub.ai/byungkyu/api-gateway).

Teams using klaviyo should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/klaviyo/SKILL.md --create-dirs "https://raw.githubusercontent.com/Demerzels-lab/elsamultiskillagent/main/public/skills/byungkyu/klaviyo/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/klaviyo/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How klaviyo Compares

Feature / AgentklaviyoStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Klaviyo API integration with managed OAuth. Access profiles, lists, segments, campaigns, flows, events, metrics, templates, catalogs, and webhooks. Use this skill when users want to manage email marketing, customer data, or integrate with Klaviyo workflows. For other third party apps, use the api-gateway skill (https://clawhub.ai/byungkyu/api-gateway).

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# Klaviyo

Access the Klaviyo API with managed OAuth authentication. Manage profiles, lists, segments, campaigns, flows, events, metrics, templates, catalogs, and webhooks for email marketing and customer engagement.

## Quick Start

```bash
# List profiles
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://gateway.maton.ai/klaviyo/api/profiles')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('revision', '2024-10-15')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
```

## Base URL

```
https://gateway.maton.ai/klaviyo/{native-api-path}
```

Replace `{native-api-path}` with the actual Klaviyo API endpoint path. The gateway proxies requests to `a.klaviyo.com` and automatically injects your OAuth token.

## Authentication

All requests require the Maton API key in the Authorization header:

```
Authorization: Bearer $MATON_API_KEY
```

**Environment Variable:** Set your API key as `MATON_API_KEY`:

```bash
export MATON_API_KEY="YOUR_API_KEY"
```

### Getting Your API Key

1. Sign in or create an account at [maton.ai](https://maton.ai)
2. Go to [maton.ai/settings](https://maton.ai/settings)
3. Copy your API key

## API Versioning

Klaviyo uses date-based API versioning. Include the `revision` header in all requests:

```
revision: 2024-10-15
```

## Connection Management

Manage your Klaviyo OAuth connections at `https://ctrl.maton.ai`.

### List Connections

```bash
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.maton.ai/connections?app=klaviyo&status=ACTIVE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
```

### Create Connection

```bash
python <<'EOF'
import urllib.request, os, json
data = json.dumps({'app': 'klaviyo'}).encode()
req = urllib.request.Request('https://ctrl.maton.ai/connections', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
```

### Get Connection

```bash
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.maton.ai/connections/{connection_id}')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
```

**Response:**
```json
{
  "connection": {
    "connection_id": "21fd90f9-5935-43cd-b6c8-bde9d915ca80",
    "status": "ACTIVE",
    "creation_time": "2025-12-08T07:20:53.488460Z",
    "last_updated_time": "2026-01-31T20:03:32.593153Z",
    "url": "https://connect.maton.ai/?session_token=...",
    "app": "klaviyo",
    "metadata": {}
  }
}
```

Open the returned `url` in a browser to complete OAuth authorization.

### Delete Connection

```bash
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.maton.ai/connections/{connection_id}', method='DELETE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
```

### Specifying Connection

If you have multiple Klaviyo connections, specify which one to use with the `Maton-Connection` header:

```bash
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://gateway.maton.ai/klaviyo/api/profiles')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('revision', '2024-10-15')
req.add_header('Maton-Connection', '21fd90f9-5935-43cd-b6c8-bde9d915ca80')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
```

If omitted, the gateway uses the default (oldest) active connection.

## API Reference

### Profiles

Manage customer data and consent.

#### Get Profiles

```bash
GET /klaviyo/api/profiles
```

Query parameters:
- `filter` - Filter profiles (e.g., `filter=equals(email,"test@example.com")`)
- `fields[profile]` - Comma-separated list of fields to include
- `page[cursor]` - Cursor for pagination
- `page[size]` - Number of results per page (max 100)
- `sort` - Sort field (prefix with `-` for descending)

**Example:**

```bash
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://gateway.maton.ai/klaviyo/api/profiles?fields[profile]=email,first_name,last_name&page[size]=10')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('revision', '2024-10-15')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
```

**Response:**
```json
{
  "data": [
    {
      "type": "profile",
      "id": "01GDDKASAP8TKDDA2GRZDSVP4H",
      "attributes": {
        "email": "alice@example.com",
        "first_name": "Alice",
        "last_name": "Johnson"
      }
    }
  ],
  "links": {
    "self": "https://a.klaviyo.com/api/profiles",
    "next": "https://a.klaviyo.com/api/profiles?page[cursor]=..."
  }
}
```

#### Get a Profile

```bash
GET /klaviyo/api/profiles/{profile_id}
```

**Example:**

```bash
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://gateway.maton.ai/klaviyo/api/profiles/01GDDKASAP8TKDDA2GRZDSVP4H')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('revision', '2024-10-15')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
```

#### Create a Profile

```bash
POST /klaviyo/api/profiles
Content-Type: application/json

{
  "data": {
    "type": "profile",
    "attributes": {
      "email": "newuser@example.com",
      "first_name": "John",
      "last_name": "Doe",
      "phone_number": "+15551234567",
      "properties": {
        "custom_field": "value"
      }
    }
  }
}
```

**Example:**

```bash
python <<'EOF'
import urllib.request, os, json
data = json.dumps({'data': {'type': 'profile', 'attributes': {'email': 'newuser@example.com', 'first_name': 'John', 'last_name': 'Doe'}}}).encode()
req = urllib.request.Request('https://gateway.maton.ai/klaviyo/api/profiles', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
req.add_header('revision', '2024-10-15')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
```

#### Update a Profile

```bash
PATCH /klaviyo/api/profiles/{profile_id}
```

**Example:**

```bash
python <<'EOF'
import urllib.request, os, json
data = json.dumps({'data': {'type': 'profile', 'id': '01GDDKASAP8TKDDA2GRZDSVP4H', 'attributes': {'first_name': 'Jane'}}}).encode()
req = urllib.request.Request('https://gateway.maton.ai/klaviyo/api/profiles/01GDDKASAP8TKDDA2GRZDSVP4H', data=data, method='PATCH')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
req.add_header('revision', '2024-10-15')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
```

#### Merge Profiles

```bash
POST /klaviyo/api/profile-merge
```

#### Get Profile Lists

```bash
GET /klaviyo/api/profiles/{profile_id}/lists
```

#### Get Profile Segments

```bash
GET /klaviyo/api/profiles/{profile_id}/segments
```

### Lists

Organize subscribers into static lists.

#### Get Lists

```bash
GET /klaviyo/api/lists
```

**Example:**

```bash
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://gateway.maton.ai/klaviyo/api/lists?fields[list]=name,created,updated')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('revision', '2024-10-15')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
```

**Response:**
```json
{
  "data": [
    {
      "type": "list",
      "id": "Y6nRLr",
      "attributes": {
        "name": "Newsletter Subscribers",
        "created": "2024-01-15T10:30:00Z",
        "updated": "2024-03-01T14:22:00Z"
      }
    }
  ]
}
```

#### Get a List

```bash
GET /klaviyo/api/lists/{list_id}
```

#### Create a List

```bash
POST /klaviyo/api/lists
```

**Example:**

```bash
python <<'EOF'
import urllib.request, os, json
data = json.dumps({'data': {'type': 'list', 'attributes': {'name': 'VIP Customers'}}}).encode()
req = urllib.request.Request('https://gateway.maton.ai/klaviyo/api/lists', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
req.add_header('revision', '2024-10-15')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
```

#### Update a List

```bash
PATCH /klaviyo/api/lists/{list_id}
```

#### Delete a List

```bash
DELETE /klaviyo/api/lists/{list_id}
```

#### Add Profiles to List

```bash
POST /klaviyo/api/lists/{list_id}/relationships/profiles
```

**Example:**

```bash
python <<'EOF'
import urllib.request, os, json
data = json.dumps({'data': [{'type': 'profile', 'id': '01GDDKASAP8TKDDA2GRZDSVP4H'}]}).encode()
req = urllib.request.Request('https://gateway.maton.ai/klaviyo/api/lists/Y6nRLr/relationships/profiles', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
req.add_header('revision', '2024-10-15')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
```

#### Remove Profiles from List

```bash
DELETE /klaviyo/api/lists/{list_id}/relationships/profiles
```

#### Get List Profiles

```bash
GET /klaviyo/api/lists/{list_id}/profiles
```

### Segments

Create dynamic audiences based on conditions.

#### Get Segments

```bash
GET /klaviyo/api/segments
```

**Example:**

```bash
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://gateway.maton.ai/klaviyo/api/segments?fields[segment]=name,created,updated')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('revision', '2024-10-15')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
```

#### Get a Segment

```bash
GET /klaviyo/api/segments/{segment_id}
```

#### Create a Segment

```bash
POST /klaviyo/api/segments
```

#### Update a Segment

```bash
PATCH /klaviyo/api/segments/{segment_id}
```

#### Delete a Segment

```bash
DELETE /klaviyo/api/segments/{segment_id}
```

#### Get Segment Profiles

```bash
GET /klaviyo/api/segments/{segment_id}/profiles
```

### Campaigns

Design and send email campaigns.

#### Get Campaigns

```bash
GET /klaviyo/api/campaigns
```

Query parameters:
- `filter` - Filter campaigns (e.g., `filter=equals(messages.channel,'email')`)
- `fields[campaign]` - Fields to include
- `sort` - Sort by field

**Example:**

```bash
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://gateway.maton.ai/klaviyo/api/campaigns?filter=equals(messages.channel,"email")')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('revision', '2024-10-15')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
```

**Response:**
```json
{
  "data": [
    {
      "type": "campaign",
      "id": "01GDDKASAP8TKDDA2GRZDSVP4I",
      "attributes": {
        "name": "Spring Sale 2024",
        "status": "Draft",
        "audiences": {
          "included": ["Y6nRLr"],
          "excluded": []
        },
        "send_options": {
          "use_smart_sending": true
        }
      }
    }
  ]
}
```

#### Get a Campaign

```bash
GET /klaviyo/api/campaigns/{campaign_id}
```

#### Create a Campaign

```bash
POST /klaviyo/api/campaigns
```

**Example:**

```bash
python <<'EOF'
import urllib.request, os, json
data = json.dumps({'data': {'type': 'campaign', 'attributes': {'name': 'Summer Newsletter', 'audiences': {'included': ['Y6nRLr']}, 'campaign-messages': {'data': [{'type': 'campaign-message', 'attributes': {'channel': 'email'}}]}}}}).encode()
req = urllib.request.Request('https://gateway.maton.ai/klaviyo/api/campaigns', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
req.add_header('revision', '2024-10-15')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
```

#### Update a Campaign

```bash
PATCH /klaviyo/api/campaigns/{campaign_id}
```

#### Delete a Campaign

```bash
DELETE /klaviyo/api/campaigns/{campaign_id}
```

#### Send a Campaign

```bash
POST /klaviyo/api/campaign-send-jobs
```

#### Get Recipient Estimation

```bash
POST /klaviyo/api/campaign-recipient-estimations
```

### Flows

Build automated customer journeys.

#### Get Flows

```bash
GET /klaviyo/api/flows
```

**Example:**

```bash
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://gateway.maton.ai/klaviyo/api/flows?fields[flow]=name,status,created,updated')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('revision', '2024-10-15')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
```

**Response:**
```json
{
  "data": [
    {
      "type": "flow",
      "id": "VJvBNr",
      "attributes": {
        "name": "Welcome Series",
        "status": "live",
        "created": "2024-01-10T08:00:00Z",
        "updated": "2024-02-15T12:30:00Z"
      }
    }
  ]
}
```

#### Get a Flow

```bash
GET /klaviyo/api/flows/{flow_id}
```

#### Create a Flow

```bash
POST /klaviyo/api/flows
```

> **Note:** Flow creation via API may be limited. Flows are typically created through the Klaviyo UI, then managed via API. Use GET, PATCH, and DELETE operations for existing flows.

#### Update Flow Status

```bash
PATCH /klaviyo/api/flows/{flow_id}
```

**Example:**

```bash
python <<'EOF'
import urllib.request, os, json
data = json.dumps({'data': {'type': 'flow', 'id': 'VJvBNr', 'attributes': {'status': 'draft'}}}).encode()
req = urllib.request.Request('https://gateway.maton.ai/klaviyo/api/flows/VJvBNr', data=data, method='PATCH')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
req.add_header('revision', '2024-10-15')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
```

#### Delete a Flow

```bash
DELETE /klaviyo/api/flows/{flow_id}
```

#### Get Flow Actions

```bash
GET /klaviyo/api/flows/{flow_id}/flow-actions
```

#### Get Flow Messages

```bash
GET /klaviyo/api/flows/{flow_id}/flow-messages
```

### Events

Track customer interactions and behaviors.

#### Get Events

```bash
GET /klaviyo/api/events
```

Query parameters:
- `filter` - Filter events (e.g., `filter=equals(metric_id,"ABC123")`)
- `fields[event]` - Fields to include
- `sort` - Sort by field (default: `-datetime`)

**Example:**

```bash
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://gateway.maton.ai/klaviyo/api/events?filter=greater-than(datetime,2024-01-01T00:00:00Z)&page[size]=50')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('revision', '2024-10-15')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
```

**Response:**
```json
{
  "data": [
    {
      "type": "event",
      "id": "4vRpBT",
      "attributes": {
        "metric_id": "TxVpCr",
        "profile_id": "01GDDKASAP8TKDDA2GRZDSVP4H",
        "datetime": "2024-03-15T14:30:00Z",
        "event_properties": {
          "value": 99.99,
          "product_name": "Running Shoes"
        }
      }
    }
  ]
}
```

#### Get an Event

```bash
GET /klaviyo/api/events/{event_id}
```

#### Create an Event

```bash
POST /klaviyo/api/events
```

**Example:**

```bash
python <<'EOF'
import urllib.request, os, json
data = json.dumps({'data': {'type': 'event', 'attributes': {'profile': {'data': {'type': 'profile', 'attributes': {'email': 'customer@example.com'}}}, 'metric': {'data': {'type': 'metric', 'attributes': {'name': 'Viewed Product'}}}, 'properties': {'product_id': 'SKU123', 'product_name': 'Blue T-Shirt', 'price': 29.99}}}}).encode()
req = urllib.request.Request('https://gateway.maton.ai/klaviyo/api/events', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
req.add_header('revision', '2024-10-15')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
```

#### Bulk Create Events

```bash
POST /klaviyo/api/event-bulk-create-jobs
```

### Metrics

Access performance data and analytics.

#### Get Metrics

```bash
GET /klaviyo/api/metrics
```

**Example:**

```bash
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://gateway.maton.ai/klaviyo/api/metrics')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('revision', '2024-10-15')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
```

**Response:**
```json
{
  "data": [
    {
      "type": "metric",
      "id": "TxVpCr",
      "attributes": {
        "name": "Placed Order",
        "created": "2024-01-01T00:00:00Z",
        "updated": "2024-03-01T00:00:00Z",
        "integration": {
          "object": "integration",
          "id": "shopify",
          "name": "Shopify"
        }
      }
    }
  ]
}
```

#### Get a Metric

```bash
GET /klaviyo/api/metrics/{metric_id}
```

#### Query Metric Aggregates

```bash
POST /klaviyo/api/metric-aggregates
```

**Example:**

```bash
python <<'EOF'
import urllib.request, os, json
data = json.dumps({'data': {'type': 'metric-aggregate', 'attributes': {'metric_id': 'TxVpCr', 'measurements': ['count', 'sum_value'], 'interval': 'day', 'filter': ['greater-or-equal(datetime,2024-01-01)', 'less-than(datetime,2024-04-01)']}}}).encode()
req = urllib.request.Request('https://gateway.maton.ai/klaviyo/api/metric-aggregates', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
req.add_header('revision', '2024-10-15')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
```

### Templates

Manage email templates.

#### Get Templates

```bash
GET /klaviyo/api/templates
```

**Example:**

```bash
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://gateway.maton.ai/klaviyo/api/templates?fields[template]=name,created,updated')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('revision', '2024-10-15')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
```

#### Get a Template

```bash
GET /klaviyo/api/templates/{template_id}
```

#### Create a Template

```bash
POST /klaviyo/api/templates
```

**Example:**

```bash
python <<'EOF'
import urllib.request, os, json
data = json.dumps({'data': {'type': 'template', 'attributes': {'name': 'Welcome Email', 'editor_type': 'CODE', 'html': '<html><body><h1>Welcome!</h1></body></html>'}}}).encode()
req = urllib.request.Request('https://gateway.maton.ai/klaviyo/api/templates', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
req.add_header('revision', '2024-10-15')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
```

#### Update a Template

```bash
PATCH /klaviyo/api/templates/{template_id}
```

#### Delete a Template

```bash
DELETE /klaviyo/api/templates/{template_id}
```

#### Render a Template

```bash
POST /klaviyo/api/template-render
```

#### Clone a Template

```bash
POST /klaviyo/api/template-clone
```

### Catalogs

Manage product catalogs.

#### Get Catalog Items

```bash
GET /klaviyo/api/catalog-items
```

**Example:**

```bash
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://gateway.maton.ai/klaviyo/api/catalog-items?fields[catalog-item]=title,price,url')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('revision', '2024-10-15')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
```

**Response:**
```json
{
  "data": [
    {
      "type": "catalog-item",
      "id": "$custom:::$default:::PROD-001",
      "attributes": {
        "title": "Blue Running Shoes",
        "price": 129.99,
        "url": "https://store.example.com/products/blue-running-shoes"
      }
    }
  ]
}
```

#### Get a Catalog Item

```bash
GET /klaviyo/api/catalog-items/{catalog_item_id}
```

#### Create Catalog Items

```bash
POST /klaviyo/api/catalog-items
```

#### Update Catalog Item

```bash
PATCH /klaviyo/api/catalog-items/{catalog_item_id}
```

#### Delete Catalog Item

```bash
DELETE /klaviyo/api/catalog-items/{catalog_item_id}
```

#### Get Catalog Variants

```bash
GET /klaviyo/api/catalog-variants
```

#### Get Catalog Categories

```bash
GET /klaviyo/api/catalog-categories
```

### Tags

Organize resources with tags.

#### Get Tags

```bash
GET /klaviyo/api/tags
```

**Example:**

```bash
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://gateway.maton.ai/klaviyo/api/tags')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('revision', '2024-10-15')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
```

#### Create a Tag

```bash
POST /klaviyo/api/tags
```

#### Update a Tag

```bash
PATCH /klaviyo/api/tags/{tag_id}
```

#### Delete a Tag

```bash
DELETE /klaviyo/api/tags/{tag_id}
```

#### Tag a Campaign

```bash
POST /klaviyo/api/tag-campaign-relationships
```

#### Tag a Flow

```bash
POST /klaviyo/api/tag-flow-relationships
```

### Coupons

Manage discount codes.

#### Get Coupons

```bash
GET /klaviyo/api/coupons
```

#### Create a Coupon

```bash
POST /klaviyo/api/coupons
```

**Example:**

```bash
python <<'EOF'
import urllib.request, os, json
data = json.dumps({'data': {'type': 'coupon', 'attributes': {'external_id': 'SUMMER_SALE_2024', 'description': 'Summer sale discount coupon'}}}).encode()
req = urllib.request.Request('https://gateway.maton.ai/klaviyo/api/coupons', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
req.add_header('revision', '2024-10-15')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
```

> **Note:** The `external_id` must match regex `^[0-9_A-z]+$` (alphanumeric and underscores only, no hyphens).

#### Get Coupon Codes

```bash
GET /klaviyo/api/coupon-codes
```

> **Note:** This endpoint requires a filter parameter. You must filter by coupon ID or profile ID.

**Example:**

```bash
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://gateway.maton.ai/klaviyo/api/coupon-codes?filter=equals(coupon.id,"SUMMER_SALE_2024")')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('revision', '2024-10-15')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
```

#### Create Coupon Codes

```bash
POST /klaviyo/api/coupon-codes
```

**Example:**

```bash
python <<'EOF'
import urllib.request, os, json
data = json.dumps({'data': {'type': 'coupon-code', 'attributes': {'unique_code': 'SAVE20NOW', 'expires_at': '2025-12-31T23:59:59Z'}, 'relationships': {'coupon': {'data': {'type': 'coupon', 'id': 'SUMMER_SALE_2024'}}}}}).encode()
req = urllib.request.Request('https://gateway.maton.ai/klaviyo/api/coupon-codes', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
req.add_header('revision', '2024-10-15')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
```

### Webhooks

Configure event notifications.

#### Get Webhooks

```bash
GET /klaviyo/api/webhooks
```

**Example:**

```bash
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://gateway.maton.ai/klaviyo/api/webhooks')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('revision', '2024-10-15')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
```

#### Create Webhook

```bash
POST /klaviyo/api/webhooks
```

**Example:**

```bash
python <<'EOF'
import urllib.request, os, json
data = json.dumps({'data': {'type': 'webhook', 'attributes': {'name': 'Order Placed Webhook', 'endpoint_url': 'https://example.com/webhooks/klaviyo', 'enabled': True}, 'relationships': {'webhook-topics': {'data': [{'type': 'webhook-topic', 'id': 'campaign:sent'}]}}}}).encode()
req = urllib.request.Request('https://gateway.maton.ai/klaviyo/api/webhooks', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
req.add_header('revision', '2024-10-15')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
```

#### Get a Webhook

```bash
GET /klaviyo/api/webhooks/{webhook_id}
```

#### Update a Webhook

```bash
PATCH /klaviyo/api/webhooks/{webhook_id}
```

#### Delete a Webhook

```bash
DELETE /klaviyo/api/webhooks/{webhook_id}
```

#### Get Webhook Topics

```bash
GET /klaviyo/api/webhook-topics
```

### Accounts

Retrieve account information.

#### Get Accounts

```bash
GET /klaviyo/api/accounts
```

**Example:**

```bash
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://gateway.maton.ai/klaviyo/api/accounts')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('revision', '2024-10-15')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
```

## Filtering

Klaviyo uses JSON:API filtering syntax. Common operators:

| Operator | Example |
|----------|---------|
| `equals` | `filter=equals(email,"test@example.com")` |
| `contains` | `filter=contains(name,"newsletter")` |
| `greater-than` | `filter=greater-than(datetime,2024-01-01T00:00:00Z)` |
| `less-than` | `filter=less-than(created,2024-03-01)` |
| `greater-or-equal` | `filter=greater-or-equal(updated,2024-01-01)` |
| `any` | `filter=any(status,["draft","scheduled"])` |

Combine filters with `and`:
```
filter=and(equals(status,"active"),greater-than(created,2024-01-01))
```

## Pagination

Klaviyo uses cursor-based pagination:

```bash
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://gateway.maton.ai/klaviyo/api/profiles?page[size]=50&page[cursor]=CURSOR_TOKEN')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('revision', '2024-10-15')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
```

Response includes pagination links:

```json
{
  "data": [...],
  "links": {
    "self": "https://a.klaviyo.com/api/profiles",
    "next": "https://a.klaviyo.com/api/profiles?page[cursor]=WzE2..."
  }
}
```

## Sparse Fieldsets

Request only specific fields to reduce response size:

```bash
# Request only email and first_name for profiles
?fields[profile]=email,first_name

# Request specific fields for included relationships
?include=lists&fields[list]=name,created
```

## Code Examples

### JavaScript

```javascript
const response = await fetch(
  'https://gateway.maton.ai/klaviyo/api/profiles?fields[profile]=email,first_name',
  {
    headers: {
      'Authorization': `Bearer ${process.env.MATON_API_KEY}`,
      'revision': '2024-10-15'
    }
  }
);
const data = await response.json();
```

### Python

```python
import os
import requests

response = requests.get(
    'https://gateway.maton.ai/klaviyo/api/profiles',
    headers={
        'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}',
        'revision': '2024-10-15'
    },
    params={'fields[profile]': 'email,first_name'}
)
data = response.json()
```

## Notes

- All requests use JSON:API specification
- Timestamps are in ISO 8601 RFC 3339 format (e.g., `2024-01-16T23:20:50.52Z`)
- Resource IDs are strings (often base64-encoded)
- Use sparse fieldsets to optimize response size
- Include `revision` header for API versioning (recommended: `2024-10-15`)
- Some POST endpoints return `200` instead of `201` for successful creation
- Coupon `external_id` must match regex `^[0-9_A-z]+$` (no hyphens)
- Coupon codes endpoint requires a filter (e.g., `filter=equals(coupon.id,"...")`)
- Flow creation via API may be limited; flows are typically created in the Klaviyo UI
- IMPORTANT: When using curl commands, use `curl -g` when URLs contain brackets (`fields[]`, `page[]`) to disable glob parsing
- IMPORTANT: When piping curl output to `jq` or other commands, environment variables like `$MATON_API_KEY` may not expand correctly in some shell environments. You may get "Invalid API key" errors when piping.

## Error Handling

| Status | Meaning |
|--------|---------|
| 400 | Bad request or missing Klaviyo connection |
| 401 | Invalid or missing Maton API key |
| 403 | Forbidden - insufficient permissions |
| 404 | Resource not found |
| 429 | Rate limited (fixed-window algorithm) |
| 4xx/5xx | Passthrough error from Klaviyo API |

### Troubleshooting: Invalid API Key

**When you receive a "Invalid API key" error, ALWAYS follow these steps before concluding there is an issue:**

1. Check that the `MATON_API_KEY` environment variable is set:

```bash
echo $MATON_API_KEY
```

2. Verify the API key is valid by listing connections:

```bash
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.maton.ai/connections')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
```

## Resources

- [Klaviyo API Documentation](https://developers.klaviyo.com)
- [API Reference](https://developers.klaviyo.com/en/reference/api_overview)
- [Klaviyo Developer Portal](https://developers.klaviyo.com/en)

Related Skills

paylock

7
from Demerzels-lab/elsamultiskillagent

Non-custodial SOL escrow for AI agent deals.

agent-reputation

7
from Demerzels-lab/elsamultiskillagent

summary: Cross-platform AI agent reputation checker with trust scoring and PayLock escrow recommendations.

Telecom Agent Skill

7
from Demerzels-lab/elsamultiskillagent

Turn your AI Agent into a Telecom Operator. Bulk calling, ChatOps, and Field Monitoring.

OpenClaw-Finnhub

7
from Demerzels-lab/elsamultiskillagent

OpenClaw skill for real-time stock quote, and financials via Finnhub API.

```markdown

7
from Demerzels-lab/elsamultiskillagent

# OpenClaw-Last.fm

security-operator

7
from Demerzels-lab/elsamultiskillagent

Runtime security guardrails for OpenClaw agents.

operator-humanizer

7
from Demerzels-lab/elsamultiskillagent

Transform AI-generated text into authentic human writing.

kit-email-operator

7
from Demerzels-lab/elsamultiskillagent

**AI-powered email marketing for Kit (ConvertKit)**.

agora

7
from Demerzels-lab/elsamultiskillagent

Trade prediction markets on Agora — the prediction market exclusively for AI agents. Register, browse markets, trade YES/NO, create markets, earn reputation via Brier scores.

surf-check

7
from Demerzels-lab/elsamultiskillagent

Surf forecast decision engine.

jinko-flight-search

7
from Demerzels-lab/elsamultiskillagent

Search flights and discover travel destinations using the Jinko MCP server. Provides two core capabilities: (1) Destination discovery — find where to travel based on criteria like budget, climate, or activities when the user has no specific destination in mind, and (2) Specific flight search — compare flights between two known cities/airports with flexible dates, cabin classes, and budget filters. Use this skill when the user wants to: search for flights, find cheap flights, discover travel destinations, compare flight prices, plan a trip, find deals from a specific city, or explore where to go. Triggers on any flight-booking, travel-planning, or destination-discovery request. Requires the Jinko MCP server connected at https://mcp.gojinko.com.

mlx-whisper

7
from Demerzels-lab/elsamultiskillagent

Local speech-to-text with MLX Whisper (Apple Silicon optimized, no API key).