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).
Install
Documentation
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://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:
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
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
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
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:
{
"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
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:
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
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)
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:
{
"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://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
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://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
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://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
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://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:
{
"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://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
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://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
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://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
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
Query parameters:
- -
filter- Filter campaigns (e.g.,filter=equals(messages.channel,'email')) - -
fields[campaign]- Fields to include - -
sort- Sort by field
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:
{
"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://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
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://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:
{
"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://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
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)
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:
{
"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://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
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://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:
{
"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://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
GET /klaviyo/api/templates
Example:
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
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': '<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
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://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:
{
"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://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
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
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://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
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://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
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://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
GET /klaviyo/api/webhooks
Example:
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
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://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
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://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:
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:
{
"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://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
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
revisionheader for API versioning (recommended:2024-10-15) - -Some POST endpoints return
200instead of201for successful creation - -Coupon
external_idmust 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 -gwhen URLs contain brackets (fields[],page[]) to disable glob parsing - -IMPORTANT: When piping curl output to
jqor other commands, environment variables like$MATON_API_KEYmay 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://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
Troubleshooting: Invalid App Name
1. Ensure your URL path starts with klaviyo. For example:
- -Correct:
https://gateway.maton.ai/klaviyo/api/profiles - -Incorrect:
https://gateway.maton.ai/api/profiles
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)
- -[Maton Community](https://discord.com/invite/dBfFAcefs2)
- -[Maton Support](mailto:support@maton.ai)
Launch an agent with Klaviyo on Termo.