klaviyo
Skill0 starsChanged 6 months agoMITView on GitHub
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).
- Reads credentials
4 other projects use a version of this.
Adopted by
Most recently taken up by
- obra/muse-skillstheir own version, first seen Oct 13, 2026
- alinaqi/claude-bootstraptheir own version, first seen Oct 8, 2026
- windsor-ai/claude-windsor-ai-plugintheir own version, first seen Sep 24, 2026
- alinaqi/maggytheir own version, first seen Jun 12, 2026
Other versions4 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 4
- alinaqi/maggy★ 711same name
- alinaqi/claude-bootstrap★ 708same name
- obra/muse-skills★ 20same name
- windsor-ai/claude-windsor-ai-plugin★ 1same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository79 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- ad-first-marketingSkill
- afrexai-community-growth-engineSkill
- agent-fleet-statusSkill
- agentgramSkill
- ai-cold-emailSkill
- answeroverflowSkill
- answeroverflowSkill
- api-gatewaySkill
- apple-notesSkill
- autonomous-operatorSkill
- autonomous-revenueSkill
- brand-analyzerSkill
- brand-identitySkill
- brand-operatorSkill
- browser-useSkill
- byteroverSkill
- calendlySkill
- clawdcursorSkill
- clawd-provisionerSkill
- client-acquisitionSkill
- cold-email-writerSkill
- cold-outreachSkill
- Community ManagerSkill
- community-mod-packSkill
- competitive-ads-extractorSkill
- competitor-analyzerSkill
- content-engineSkill
- content-qa-scorerSkill
- content-repurposeSkill
- cron-automatorSkill
- daily-brief-generatorSkill
- deep-researchSkill
- elite-longterm-memorySkill
- email-responderSkill
- fathom-tele-tvSkill
- fleet-commanderSkill
- frontend-designSkill
- gogSkill
- himalayaSkill
- imsgSkill
- internet-marketingSkill
- knowledge-extractorSkill
- koino-frontendSkill
- lead-research-assistantSkill
- lead-scorerSkill
- macos-calendarSkill
- marketing-drafterSkill
- marketingSkill
- marketing-strategy-pmmSkill
- master-marketingSkill
- meeting-prepSkill
- moltbookSkill
- moltguardSkill
- objection-destroyerSkill
- ontologySkill
- pipeline-autopilotSkill
- marketing-ideasSkill
- proactive-agentSkill
- proposal-generatorSkill
- The first 60 shown.
The file
We split this skill into the rules it gives an agent
9 rules. 0 are common, 6 are distinctive, and 3 are very specific to this project.
0
Common
Most of the 4 edited versions we read keep these.
6
Distinctive
This author's own choices. Worth a look.
3
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 43
All requests require the Maton API key in the Authorization header:
- Very specific: line 138
If you have multiple Klaviyo connections, specify which one to use with the Maton-Connection header:
- Distinctive: line 151
If omitted, the gateway uses the default (oldest) active connection.
- Distinctive: line 408
Create dynamic audiences based on conditions.
- Distinctive: line 1251
All requests use JSON:API specification
- Distinctive: line 1254
Use sparse fieldsets to optimize response size
- Very specific: line 1276
Check that the MATON_API_KEY environment variable is set:
- Distinctive: line 1282
Verify the API key is valid by listing connections:
- Very specific: line 1295
Ensure your URL path starts with klaviyo.
“Common” is measured: kept by at least 6 in 10 of the 4 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
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))
EOFBase 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_KEYEnvironment 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: 2024-10-15Connection 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))
EOFCreate 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))
EOFGet 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))
EOFResponse:
{
"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))
EOFSpecifying 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))
EOFIf omitted, the gateway uses the default (oldest) active connection.
API Reference
Profiles
Manage customer data and consent.
Get Profiles
GET /klaviyo/api/profilesQuery parameters:
filter- Filter profiles (e.g.,filter=equals(email,"test@example.com"))fields[profile]- Comma-separated list of fields to includepage[cursor]- Cursor for paginationpage[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://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))
EOFResponse:
{
"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))
EOFCreate 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))
EOFUpdate 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))
EOFMerge Profiles
POST /klaviyo/api/profile-mergeGet Profile Lists
GET /klaviyo/api/profiles/{profile_id}/listsGet Profile Segments
GET /klaviyo/api/profiles/{profile_id}/segmentsLists
Organize subscribers into static lists.
Get Lists
GET /klaviyo/api/listsExample:
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))
EOFResponse:
{
"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/listsExample:
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))
EOFUpdate 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/profilesExample:
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))
EOFRemove Profiles from List
DELETE /klaviyo/api/lists/{list_id}/relationships/profilesGet List Profiles
GET /klaviyo/api/lists/{list_id}/profilesSegments
Create dynamic audiences based on conditions.
Get Segments
GET /klaviyo/api/segmentsExample:
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))
EOFGet a Segment
GET /klaviyo/api/segments/{segment_id}Create a Segment
POST /klaviyo/api/segmentsUpdate 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}/profilesCampaigns
Design and send email campaigns.
Get Campaigns
GET /klaviyo/api/campaignsQuery parameters:
filter- Filter campaigns (e.g.,filter=equals(messages.channel,'email'))fields[campaign]- Fields to includesort- Sort by field
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', '2024-10-15')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOFResponse:
{
"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/campaignsExample:
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))
EOFUpdate 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-jobsGet Recipient Estimation
POST /klaviyo/api/campaign-recipient-estimationsFlows
Build automated customer journeys.
Get Flows
GET /klaviyo/api/flowsExample:
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))
EOFResponse:
{
"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/flowsNote: 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))
EOFDelete a Flow
DELETE /klaviyo/api/flows/{flow_id}Get Flow Actions
GET /klaviyo/api/flows/{flow_id}/flow-actionsGet Flow Messages
GET /klaviyo/api/flows/{flow_id}/flow-messagesEvents
Track customer interactions and behaviors.
Get Events
GET /klaviyo/api/eventsQuery parameters:
filter- Filter events (e.g.,filter=equals(metric_id,"ABC123"))fields[event]- Fields to includesort- Sort by field (default:-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', '2024-10-15')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOFResponse:
{
"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/eventsExample:
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))
EOFBulk Create Events
POST /klaviyo/api/event-bulk-create-jobsMetrics
Access performance data and analytics.
Get Metrics
GET /klaviyo/api/metricsExample:
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))
EOFResponse:
{
"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-aggregatesExample:
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))
EOFTemplates
Manage email templates.
Get Templates
GET /klaviyo/api/templatesExample:
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))
EOFGet a Template
GET /klaviyo/api/templates/{template_id}Create a Template
POST /klaviyo/api/templatesExample:
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))
EOFUpdate a Template
PATCH /klaviyo/api/templates/{template_id}Delete a Template
DELETE /klaviyo/api/templates/{template_id}Render a Template
POST /klaviyo/api/template-renderClone a Template
POST /klaviyo/api/template-cloneCatalogs
Manage product catalogs.
Get Catalog Items
GET /klaviyo/api/catalog-itemsExample:
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))
EOFResponse:
{
"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-itemsUpdate 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-variantsGet Catalog Categories
GET /klaviyo/api/catalog-categoriesTags
Organize resources with tags.
Get Tags
GET /klaviyo/api/tagsExample:
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))
EOFCreate a Tag
POST /klaviyo/api/tagsUpdate 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-relationshipsTag a Flow
POST /klaviyo/api/tag-flow-relationshipsCoupons
Manage discount codes.
Get Coupons
GET /klaviyo/api/couponsCreate a Coupon
POST /klaviyo/api/couponsExample:
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))
EOFNote: The
external_idmust match regex^[0-9_A-z]+$(alphanumeric and underscores only, no hyphens).
Get Coupon Codes
GET /klaviyo/api/coupon-codesNote: 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))
EOFCreate Coupon Codes
POST /klaviyo/api/coupon-codesExample:
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))
EOFWebhooks
Configure event notifications.
Get Webhooks
GET /klaviyo/api/webhooksExample:
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))
EOFCreate Webhook
POST /klaviyo/api/webhooksExample:
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))
EOFGet 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-topicsAccounts
Retrieve account information.
Get Accounts
GET /klaviyo/api/accountsExample:
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))
EOFFiltering
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))
EOFResponse 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,createdCode 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
- Check that the
MATON_API_KEYenvironment variable is set:
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))
EOFTroubleshooting: Invalid App Name
- 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
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

