Skills klaviyo
git clone https://github.com/openclaw/skills
T=$(mktemp -d) && git clone --depth=1 https://github.com/openclaw/skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/0xspeter/klaviyo-1-0-4" ~/.claude/skills/openclaw-skills-klaviyo && rm -rf "$T"
T=$(mktemp -d) && git clone --depth=1 https://github.com/openclaw/skills "$T" && mkdir -p ~/.openclaw/skills && cp -r "$T/skills/0xspeter/klaviyo-1-0-4" ~/.openclaw/skills/openclaw-skills-klaviyo && rm -rf "$T"
skills/0xspeter/klaviyo-1-0-4/SKILL.mdKlaviyo
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', '2026-01-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
- Sign in or create an account at maton.ai
- Go to maton.ai/settings
- 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://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', '2026-01-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 profiles (e.g.,filter
)filter=equals(email,"test@example.com")
- Comma-separated list of fields to includefields[profile]
- Cursor for paginationpage[cursor]
- Number of results per page (max 100)page[size]
- Sort field (prefix withsort
for descending)-
Example:
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', '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://gateway.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://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', '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://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', '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://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', '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://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', '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://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', '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://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', '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
orfilter=equals(messages.channel,"email").filter=equals(messages.channel,"sms")
Query parameters:
- Required. Filter by channel (e.g.,filter
)filter=equals(messages.channel,"email")
- Fields to includefields[campaign]
- Sort by fieldsort
Example:
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', '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://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', '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://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', '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://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', '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 events (e.g.,filter
)filter=equals(metric_id,"ABC123")
- Fields to includefields[event]
- Sort by field (default:sort
)-datetime
Example:
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', '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://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', '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://gateway.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://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', '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://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', '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': '<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', '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://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', '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://gateway.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://gateway.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://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', '2026-01-15') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF
Note: The
must match regexexternal_id(alphanumeric and underscores only, no hyphens).^[0-9_A-z]+$
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', '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://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', '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://gateway.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://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', '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://gateway.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://gateway.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://gateway.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://gateway.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://gateway.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://gateway.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://gateway.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://gateway.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 |
|---|---|
| |
| |
| |
| |
| |
| |
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', '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://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
header for API versioning (recommended:revision
)2026-01-15 - Some POST endpoints return
instead of200
for successful creation201 - Coupon
must match regexexternal_id
(no hyphens)^[0-9_A-z]+$ - 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
when URLs contain brackets (curl -g
,fields[]
) to disable glob parsingpage[] - IMPORTANT: When piping curl output to
or other commands, environment variables likejq
may not expand correctly in some shell environments. You may get "Invalid API key" errors when piping.$MATON_API_KEY
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
- Check that the
environment variable is set:MATON_API_KEY
echo $MATON_API_KEY
- 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
- Ensure your URL path starts with
. For example:klaviyo
- Correct:
https://gateway.maton.ai/klaviyo/api/profiles - Incorrect:
https://gateway.maton.ai/api/profiles