🎁 Get the FREE AI Skills Starter Guide β€” Subscribe β†’
BytesAgainBytesAgain
πŸ¦€ ClawHub

Klaviyo

by @byungkyu

Klaviyo API integration with managed OAuth. Access profiles, lists, segments, campaigns, flows, events, metrics, templates, catalogs, and webhooks. Use this...

Versionv1.0.5
Downloads17,259
Stars⭐ 8
Comments1
TERMINAL
clawhub install klaviyo

πŸ“– About This Skill


name: klaviyo description: | 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). compatibility: Requires network access and valid Maton API key metadata: author: maton version: "1.0" clawdbot: emoji: 🧠 requires: env: - MATON_API_KEY

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

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

Base URL

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

Maton 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:

export MATON_API_KEY="YOUR_API_KEY"

Getting Your API Key

1. Sign in or create an account at maton.ai 2. Go to maton.ai/settings 3. Copy your API key

API Versioning

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

revision: 2026-01-15

Connection Management

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

List Connections

python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.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

python <<'EOF'
import urllib.request, os, json
data = json.dumps({'app': 'klaviyo'}).encode()
req = urllib.request.Request('https://api.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

python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.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:

{
  "connection": {
    "connection_id": "{connection_id}",
    "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

python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.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:

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

If you have multiple connections, always include this header to ensure requests go to the intended account.

Security & Permissions

  • Access is scoped to profiles, lists, segments, campaigns, flows, events, metrics, templates, catalogs, and webhooks within the connected Klaviyo account.
  • All write operations require explicit user approval. Before executing any create, update, or delete call, confirm the target resource and intended effect with the user.
  • API Reference

    Profiles

    Manage customer data and consent.

    #### Get Profiles

    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:

    python <<'EOF'
    import urllib.request, os, json
    req = urllib.request.Request('https://api.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', '2026-01-15')
    print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
    EOF
    

    Response:

    {
      "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

    GET /klaviyo/api/profiles/{profile_id}
    

    Example:

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

    #### Create a Profile

    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:

    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://api.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', '2026-01-15')
    print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
    EOF
    

    #### Update a Profile

    PATCH /klaviyo/api/profiles/{profile_id}
    

    Example:

    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://api.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', '2026-01-15')
    print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
    EOF
    

    #### Merge Profiles

    POST /klaviyo/api/profile-merge
    

    #### Get Profile Lists

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

    #### Get Profile Segments

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

    Lists

    Organize subscribers into static lists.

    #### Get Lists

    GET /klaviyo/api/lists
    

    Example:

    python <<'EOF'
    import urllib.request, os, json
    req = urllib.request.Request('https://api.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', '2026-01-15')
    print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
    EOF
    

    Response:

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

    #### Get a List

    GET /klaviyo/api/lists/{list_id}
    

    #### Create a List

    POST /klaviyo/api/lists
    

    Example:

    python <<'EOF'
    import urllib.request, os, json
    data = json.dumps({'data': {'type': 'list', 'attributes': {'name': 'VIP Customers'}}}).encode()
    req = urllib.request.Request('https://api.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', '2026-01-15')
    print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
    EOF
    

    #### Update a List

    PATCH /klaviyo/api/lists/{list_id}
    

    #### Delete a List

    DELETE /klaviyo/api/lists/{list_id}
    

    #### Add Profiles to List

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

    Example:

    python <<'EOF'
    import urllib.request, os, json
    data = json.dumps({'data': [{'type': 'profile', 'id': '01GDDKASAP8TKDDA2GRZDSVP4H'}]}).encode()
    req = urllib.request.Request('https://api.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', '2026-01-15')
    print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
    EOF
    

    #### Remove Profiles from List

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

    #### Get List Profiles

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

    Segments

    Create dynamic audiences based on conditions.

    #### Get Segments

    GET /klaviyo/api/segments
    

    Example:

    python <<'EOF'
    import urllib.request, os, json
    req = urllib.request.Request('https://api.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', '2026-01-15')
    print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
    EOF
    

    #### Get a Segment

    GET /klaviyo/api/segments/{segment_id}
    

    #### Create a Segment

    POST /klaviyo/api/segments
    

    #### Update a Segment

    PATCH /klaviyo/api/segments/{segment_id}
    

    #### Delete a Segment

    DELETE /klaviyo/api/segments/{segment_id}
    

    #### Get Segment Profiles

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

    Campaigns

    Design and send email campaigns.

    #### Get Campaigns

    GET /klaviyo/api/campaigns
    

    > Note: A channel filter is required. Use filter=equals(messages.channel,"email") or filter=equals(messages.channel,"sms").

    Query parameters:

  • filter - Required. Filter by channel (e.g., filter=equals(messages.channel,"email"))
  • fields[campaign] - Fields to include
  • sort - Sort by field
  • Example:

    python <<'EOF'
    import urllib.request, os, json
    req = urllib.request.Request('https://api.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', '2026-01-15')
    print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
    EOF
    

    Response:

    {
      "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

    GET /klaviyo/api/campaigns/{campaign_id}
    

    #### Create a Campaign

    POST /klaviyo/api/campaigns
    

    Example:

    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://api.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', '2026-01-15')
    print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
    EOF
    

    #### Update a Campaign

    PATCH /klaviyo/api/campaigns/{campaign_id}
    

    #### Delete a Campaign

    DELETE /klaviyo/api/campaigns/{campaign_id}
    

    #### Send a Campaign

    POST /klaviyo/api/campaign-send-jobs
    

    #### Get Recipient Estimation

    POST /klaviyo/api/campaign-recipient-estimations
    

    Flows

    Build automated customer journeys.

    #### Get Flows

    GET /klaviyo/api/flows
    

    Example:

    python <<'EOF'
    import urllib.request, os, json
    req = urllib.request.Request('https://api.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', '2026-01-15')
    print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
    EOF
    

    Response:

    {
      "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

    GET /klaviyo/api/flows/{flow_id}
    

    #### Create a Flow

    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

    PATCH /klaviyo/api/flows/{flow_id}
    

    Example:

    python <<'EOF'
    import urllib.request, os, json
    data = json.dumps({'data': {'type': 'flow', 'id': 'VJvBNr', 'attributes': {'status': 'draft'}}}).encode()
    req = urllib.request.Request('https://api.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', '2026-01-15')
    print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
    EOF
    

    #### Delete a Flow

    DELETE /klaviyo/api/flows/{flow_id}
    

    #### Get Flow Actions

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

    #### Get Flow Messages

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

    Events

    Track customer interactions and behaviors.

    #### Get Events

    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:

    python <<'EOF'
    import urllib.request, os, json
    req = urllib.request.Request('https://api.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', '2026-01-15')
    print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
    EOF
    

    Response:

    {
      "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

    GET /klaviyo/api/events/{event_id}
    

    #### Create an Event

    POST /klaviyo/api/events
    

    Example:

    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://api.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', '2026-01-15')
    print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
    EOF
    

    #### Bulk Create Events

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

    Metrics

    Access performance data and analytics.

    #### Get Metrics

    GET /klaviyo/api/metrics
    

    Example:

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

    Response:

    {
      "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

    GET /klaviyo/api/metrics/{metric_id}
    

    #### Query Metric Aggregates

    POST /klaviyo/api/metric-aggregates
    

    Example:

    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://api.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', '2026-01-15')
    print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
    EOF
    

    Templates

    Manage email templates.

    #### Get Templates

    GET /klaviyo/api/templates
    

    Example:

    python <<'EOF'
    import urllib.request, os, json
    req = urllib.request.Request('https://api.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', '2026-01-15')
    print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
    EOF
    

    #### Get a Template

    GET /klaviyo/api/templates/{template_id}
    

    #### Create a Template

    POST /klaviyo/api/templates
    

    Example:

    python <<'EOF'
    import urllib.request, os, json
    data = json.dumps({'data': {'type': 'template', 'attributes': {'name': 'Welcome Email', 'editor_type': 'CODE', 'html': '

    Welcome!

    '}}}).encode() req = urllib.request.Request('https://api.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', '2026-01-15') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF

    #### Update a Template

    PATCH /klaviyo/api/templates/{template_id}
    

    #### Delete a Template

    DELETE /klaviyo/api/templates/{template_id}
    

    #### Render a Template

    POST /klaviyo/api/template-render
    

    #### Clone a Template

    POST /klaviyo/api/template-clone
    

    Catalogs

    Manage product catalogs.

    #### Get Catalog Items

    GET /klaviyo/api/catalog-items
    

    Example:

    python <<'EOF'
    import urllib.request, os, json
    req = urllib.request.Request('https://api.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', '2026-01-15')
    print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
    EOF
    

    Response:

    {
      "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

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

    #### Create Catalog Items

    POST /klaviyo/api/catalog-items
    

    #### Update Catalog Item

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

    #### Delete Catalog Item

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

    #### Get Catalog Variants

    GET /klaviyo/api/catalog-variants
    

    #### Get Catalog Categories

    GET /klaviyo/api/catalog-categories
    

    Tags

    Organize resources with tags.

    #### Get Tags

    GET /klaviyo/api/tags
    

    Example:

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

    #### Create a Tag

    POST /klaviyo/api/tags
    

    #### Update a Tag

    PATCH /klaviyo/api/tags/{tag_id}
    

    #### Delete a Tag

    DELETE /klaviyo/api/tags/{tag_id}
    

    #### Tag a Campaign

    POST /klaviyo/api/tag-campaign-relationships
    

    #### Tag a Flow

    POST /klaviyo/api/tag-flow-relationships
    

    #### Get Tag Groups

    GET /klaviyo/api/tag-groups
    

    Example:

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

    #### Create Tag Group

    POST /klaviyo/api/tag-groups
    

    #### Update Tag Group

    PATCH /klaviyo/api/tag-groups/{tag_group_id}
    

    #### Delete Tag Group

    DELETE /klaviyo/api/tag-groups/{tag_group_id}
    

    Coupons

    Manage discount codes.

    #### Get Coupons

    GET /klaviyo/api/coupons
    

    #### Create a Coupon

    POST /klaviyo/api/coupons
    

    Example:

    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://api.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', '2026-01-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

    GET /klaviyo/api/coupon-codes
    

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

    Example:

    python <<'EOF'
    import urllib.request, os, json
    req = urllib.request.Request('https://api.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', '2026-01-15')
    print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
    EOF
    

    #### Create Coupon Codes

    POST /klaviyo/api/coupon-codes
    

    Example:

    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://api.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', '2026-01-15')
    print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
    EOF
    

    Webhooks

    Configure event notifications.

    #### Get Webhooks

    GET /klaviyo/api/webhooks
    

    Example:

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

    #### Create Webhook

    POST /klaviyo/api/webhooks
    

    Example:

    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://api.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', '2026-01-15')
    print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
    EOF
    

    #### Get a Webhook

    GET /klaviyo/api/webhooks/{webhook_id}
    

    #### Update a Webhook

    PATCH /klaviyo/api/webhooks/{webhook_id}
    

    #### Delete a Webhook

    DELETE /klaviyo/api/webhooks/{webhook_id}
    

    #### Get Webhook Topics

    GET /klaviyo/api/webhook-topics
    

    Accounts

    Retrieve account information.

    #### Get Accounts

    GET /klaviyo/api/accounts
    

    Example:

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

    Images

    Manage uploaded images.

    #### Get Images

    GET /klaviyo/api/images
    

    Example:

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

    #### Get an Image

    GET /klaviyo/api/images/{image_id}
    

    #### Upload Image from URL

    POST /klaviyo/api/images
    

    Example:

    python <<'EOF'
    import urllib.request, os, json
    data = json.dumps({'data': {'type': 'image', 'attributes': {'import_from_url': 'https://example.com/image.jpg', 'name': 'Product Image'}}}).encode()
    req = urllib.request.Request('https://api.maton.ai/klaviyo/api/images', 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', '2026-01-15')
    print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
    EOF
    

    Forms

    Manage signup forms.

    #### Get Forms

    GET /klaviyo/api/forms
    

    Example:

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

    #### Get a Form

    GET /klaviyo/api/forms/{form_id}
    

    #### Get Form Versions

    GET /klaviyo/api/forms/{form_id}/form-versions
    

    Reviews

    Manage product reviews.

    #### Get Reviews

    GET /klaviyo/api/reviews
    

    Example:

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

    #### Get a Review

    GET /klaviyo/api/reviews/{review_id}
    

    #### Update Review

    PATCH /klaviyo/api/reviews/{review_id}
    

    Universal Content

    Manage reusable email content blocks.

    #### Get Universal Content

    GET /klaviyo/api/template-universal-content
    

    Example:

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

    #### Create Universal Content

    POST /klaviyo/api/template-universal-content
    

    #### Update Universal Content

    PATCH /klaviyo/api/template-universal-content/{content_id}
    

    #### Delete Universal Content

    DELETE /klaviyo/api/template-universal-content/{content_id}
    

    Bulk Profile Subscriptions

    Manage email/SMS subscriptions in bulk.

    #### Bulk Subscribe Profiles

    POST /klaviyo/api/profile-subscription-bulk-create-jobs
    

    Example:

    python <<'EOF'
    import urllib.request, os, json
    data = json.dumps({
        'data': {
            'type': 'profile-subscription-bulk-create-job',
            'attributes': {
                'profiles': {
                    'data': [{
                        'type': 'profile',
                        'attributes': {
                            'email': 'newsubscriber@example.com',
                            'subscriptions': {
                                'email': {'marketing': {'consent': 'SUBSCRIBED'}}
                            }
                        }
                    }]
                }
            },
            'relationships': {
                'list': {'data': {'type': 'list', 'id': 'LIST_ID'}}
            }
        }
    }).encode()
    req = urllib.request.Request('https://api.maton.ai/klaviyo/api/profile-subscription-bulk-create-jobs', 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', '2026-01-15')
    print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
    EOF
    

    #### Bulk Unsubscribe Profiles

    POST /klaviyo/api/profile-subscription-bulk-delete-jobs
    

    #### Bulk Suppress Profiles

    POST /klaviyo/api/profile-suppression-bulk-create-jobs
    

    #### Bulk Unsuppress Profiles

    POST /klaviyo/api/profile-suppression-bulk-delete-jobs
    

    Profile Bulk Import

    Import profiles in bulk.

    #### Get Bulk Import Jobs

    GET /klaviyo/api/profile-bulk-import-jobs
    

    Example:

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

    #### Create Bulk Import Job

    POST /klaviyo/api/profile-bulk-import-jobs
    

    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:

    python <<'EOF'
    import urllib.request, os, json
    req = urllib.request.Request('https://api.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', '2026-01-15')
    print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
    EOF
    

    Response includes pagination links:

    {
      "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:

    # 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

    const response = await fetch(
      'https://api.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

    import os
    import requests

    response = requests.get( 'https://api.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: 2026-01-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: API Key Issues

    1. Check that the MATON_API_KEY environment variable is set:

    echo $MATON_API_KEY
    

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

    python <<'EOF'
    import urllib.request, os, json
    req = urllib.request.Request('https://api.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
    

    Troubleshooting: Invalid App Name

    1. Ensure your URL path starts with klaviyo. For example:

  • Correct: https://api.maton.ai/klaviyo/api/profiles
  • Incorrect: https://api.maton.ai/api/profiles
  • Resources

  • Klaviyo API Documentation
  • API Reference
  • Klaviyo Developer Portal
  • Maton Community
  • Maton Support
  • πŸ’‘ Examples

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

    πŸ“‹ Tips & Best Practices

  • 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: 2026-01-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.