Skill: byungkyu/klaviyo (version 1.0.5)

--- 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 ```bash # 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`: ```bash export MATON_API_KEY="YOUR_API_KEY" ``` ### Getting Your API Key 1. Sign in or create an account at [maton.ai](https://maton.ai) 2. Go to [maton.ai/settings](https://maton.ai/settings) 3. Copy your API key ## API Versioning Klaviyo uses date-based API versioning. Include the `revision` header in all requests: ``` revision: 2026-01-15 ``` ## Connection Management Manage your Klaviyo OAuth connections at `https://api.maton.ai`. ### List Connections ```bash 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 ```bash 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 ```bash 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:** ```json { "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 ```bash 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: ```bash 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 ```bash GET /klaviyo/api/profiles ``` Query parameters: - `filter` - Filter profiles (e.g., `filter=equals(email,"[REDACTED_SECRET]")`) - `fields[profile]` - Comma-separated list of fields to include - `page[cursor]` - Cursor for pagination - `page[size]` - Number of results per page (max 100) - `sort` - Sort field (prefix with `-` for descending) **Example:** ```bash python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://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:** ```json { "data": [ { "type": "profile", "id": "01GDDKASAP8TKDDA2GRZDSVP4H", "attributes": { "email": "[REDACTED_SECRET]", "first_name": "Alice", "last_name": "Johnson" } } ], "links": { "self": "https://a.klaviyo.com/api/profiles", "next": "https://a.klaviyo.com/api/profiles?page[cursor]=..." } } ``` #### Get a Profile ```bash GET /klaviyo/api/profiles/{profile_id} ``` **Example:** ```bash python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://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 ```bash POST /klaviyo/api/profiles Content-Type: application/json { "data": { "type": "profile", "attributes": { "email": "[REDACTED_SECRET]", "first_name": "John", "last_name": "Doe", "phone_number": "+15551234567", "properties": { "custom_field": "value" } } } } ``` **Example:** ```bash python <<'EOF' import urllib.request, os, json data = json.dumps({'data': {'type': 'profile', 'attributes': {'email': '[REDACTED_SECRET]', '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 ```bash PATCH /klaviyo/api/profiles/{profile_id} ``` **Example:** ```bash python <<'EOF' import urllib.request, os, json data = json.dumps({'data': {'type': 'profile', 'id': '01GDDKASAP8TKDDA2GRZDSVP4H', 'attributes': {'first_name': 'Jane'}}}).encode() req = urllib.request.Request('https://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 ```bash POST /klaviyo/api/profile-merge ``` #### Get Profile Lists ```bash GET /klaviyo/api/profiles/{profile_id}/lists ``` #### Get Profile Segments ```bash GET /klaviyo/api/profiles/{profile_id}/segments ``` ### Lists Organize subscribers into static lists. #### Get Lists ```bash GET /klaviyo/api/lists ``` **Example:** ```bash python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://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:** ```json { "data": [ { "type": "list", "id": "Y6nRLr", "attributes": { "name": "Newsletter Subscribers", "created": "2024-01-15T10:30:00Z", "updated": "2024-03-01T14:22:00Z" } } ] } ``` #### Get a List ```bash GET /klaviyo/api/lists/{list_id} ``` #### Create a List ```bash POST /klaviyo/api/lists ``` **Example:** ```bash python <<'EOF' import urllib.request, os, json data = json.dumps({'data': {'type': 'list', 'attributes': {'name': 'VIP Customers'}}}).encode() req = urllib.request.Request('https://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 ```bash PATCH /klaviyo/api/lists/{list_id} ``` #### Delete a List ```bash DELETE /klaviyo/api/lists/{list_id} ``` #### Add Profiles to List ```bash POST /klaviyo/api/lists/{list_id}/relationships/profiles ``` **Example:** ```bash python <<'EOF' import urllib.request, os, json data = json.dumps({'data': [{'type': 'profile', 'id': '01GDDKASAP8TKDDA2GRZDSVP4H'}]}).encode() req = urllib.request.Request('https://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 ```bash DELETE /klaviyo/api/lists/{list_id}/relationships/profiles ``` #### Get List Profiles ```bash GET /klaviyo/api/lists/{list_id}/profiles ``` ### Segments Create dynamic audiences based on conditions. #### Get Segments ```bash GET /klaviyo/api/segments ``` **Example:** ```bash python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://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 ```bash GET /klaviyo/api/segments/{segment_id} ``` #### Create a Segment ```bash POST /klaviyo/api/segments ``` #### Update a Segment ```bash PATCH /klaviyo/api/segments/{segment_id} ``` #### Delete a Segment ```bash DELETE /klaviyo/api/segments/{segment_id} ``` #### Get Segment Profiles ```bash GET /klaviyo/api/segments/{segment_id}/profiles ``` ### Campaigns Design and send email campaigns. #### Get Campaigns ```bash GET /klaviyo/api/campaigns ``` > **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:** ```bash 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:** ```json { "data": [ { "type": "campaign", "id": "01GDDKASAP8TKDDA2GRZDSVP4I", "attributes": { "name": "Spring Sale 2024", "status": "Draft", "audiences": { "included": ["Y6nRLr"], "excluded": [] }, "send_options": { "use_smart_sending": true } } } ] } ``` #### Get a Campaign ```bash GET /klaviyo/api/campaigns/{campaign_id} ``` #### Create a Campaign ```bash POST /klaviyo/api/campaigns ``` **Example:** ```bash python <<'EOF' import urllib.request, os, json data = json.dumps({'data': {'type': 'campaign', 'attributes': {'name': 'Summer Newsletter', 'audiences': {'included': ['Y6nRLr']}, 'campaign-messages': {'data': [{'type': 'campaign-message', 'attributes': {'channel': 'email'}}]}}}}).encode() req = urllib.request.Request('https://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 ```bash PATCH /klaviyo/api/campaigns/{campaign_id} ``` #### Delete a Campaign ```bash DELETE /klaviyo/api/campaigns/{campaign_id} ``` #### Send a Campaign ```bash POST /klaviyo/api/campaign-send-jobs ``` #### Get Recipient Estimation ```bash POST /klaviyo/api/campaign-recipient-estimations ``` ### Flows Build automated customer journeys. #### Get Flows ```bash GET /klaviyo/api/flows ``` **Example:** ```bash python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://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:** ```json { "data": [ { "type": "flow", "id": "VJvBNr", "attributes": { "name": "Welcome Series", "status": "live", "created": "2024-01-10T08:00:00Z", "updated": "2024-02-15T12:30:00Z" } } ] } ``` #### Get a Flow ```bash GET /klaviyo/api/flows/{flow_id} ``` #### Create a Flow ```bash POST /klaviyo/api/flows ``` > **Note:** Flow creation via API may be limited. Flows are typically created through the Klaviyo UI, then managed via API. Use GET, PATCH, and DELETE operations for existing flows. #### Update Flow Status ```bash PATCH /klaviyo/api/flows/{flow_id} ``` **Example:** ```bash python <<'EOF' import urllib.request, os, json data = json.dumps({'data': {'type': 'flow', 'id': 'VJvBNr', 'attributes': {'status': 'draft'}}}).encode() req = urllib.request.Request('https://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 ```bash DELETE /klaviyo/api/flows/{flow_id} ``` #### Get Flow Actions ```bash GET /klaviyo/api/flows/{flow_id}/flow-actions ``` #### Get Flow Messages ```bash GET /klaviyo/api/flows/{flow_id}/flow-messages ``` ### Events Track customer interactions and behaviors. #### Get Events ```bash GET /klaviyo/api/events ``` Query parameters: - `filter` - Filter events (e.g., `filter=equals(metric_id,"ABC123")`) - `fields[event]` - Fields to include - `sort` - Sort by field (default: `-datetime`) **Example:** ```bash python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://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:** ```json { "data": [ { "type": "event", "id": "4vRpBT", "attributes": { "metric_id": "TxVpCr", "profile_id": "01GDDKASAP8TKDDA2GRZDSVP4H", "datetime": "2024-03-15T14:30:00Z", "event_properties": { "value": 99.99, "product_name": "Running Shoes" } } } ] } ``` #### Get an Event ```bash GET /klaviyo/api/events/{event_id} ``` #### Create an Event ```bash POST /klaviyo/api/events ``` **Example:** ```bash python <<'EOF' import urllib.request, os, json data = json.dumps({'data': {'type': 'event', 'attributes': {'profile': {'data': {'type': 'profile', 'attributes': {'email': '[REDACTED_SECRET]'}}}, '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 ```bash POST /klaviyo/api/event-bulk-create-jobs ``` ### Metrics Access performance data and analytics. #### Get Metrics ```bash GET /klaviyo/api/metrics ``` **Example:** ```bash python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://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:** ```json { "data": [ { "type": "metric", "id": "TxVpCr", "attributes": { "name": "Placed Order", "created": "2024-01-01T00:00:00Z", "updated": "2024-03-01T00:00:00Z", "integration": { "object": "integration", "id": "shopify", "name": "Shopify" } } } ] } ``` #### Get a Metric ```bash GET /klaviyo/api/metrics/{metric_id} ``` #### Query Metric Aggregates ```bash POST /klaviyo/api/metric-aggregates ``` **Example:** ```bash python <<'EOF' import urllib.request, os, json data = json.dumps({'data': {'type': 'metric-aggregate', 'attributes': {'metric_id': 'TxVpCr', 'measurements': ['count', 'sum_value'], 'interval': 'day', 'filter': ['greater-or-equal(datetime,2024-01-01)', 'less-than(datetime,2024-04-01)']}}}).encode() req = urllib.request.Request('https://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 ```bash GET /klaviyo/api/templates ``` **Example:** ```bash 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 ```bash GET /klaviyo/api/templates/{template_id} ``` #### Create a Template ```bash POST /klaviyo/api/templates ``` **Example:** ```bash python <<'EOF' import urllib.request, os, json data = json.dumps({'data': {'type': 'template', 'attributes': {'name': 'Welcome Email', 'editor_type': 'CODE', 'html': '<html><body><h1>Welcome!</h1></body></html>'}}}).encode() req = urllib.request.Request('https://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 ```bash PATCH /klaviyo/api/templates/{template_id} ``` #### Delete a Template ```bash DELETE /klaviyo/api/templates/{template_id} ``` #### Render a Template ```bash POST /klaviyo/api/template-render ``` #### Clone a Template ```bash POST /klaviyo/api/template-clone ``` ### Catalogs Manage product catalogs. #### Get Catalog Items ```bash GET /klaviyo/api/catalog-items ``` **Example:** ```bash python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://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:** ```json { "data": [ { "type": "catalog-item", "id": "$custom:::$default:::PROD-001", "attributes": { "title": "Blue Running Shoes", "price": 129.99, "url": "https://store.example.com/products/blue-running-shoes" } } ] } ``` #### Get a Catalog Item ```bash GET /klaviyo/api/catalog-items/{catalog_item_id} ``` #### Create Catalog Items ```bash POST /klaviyo/api/catalog-items ``` #### Update Catalog Item ```bash PATCH /klaviyo/api/catalog-items/{catalog_item_id} ``` #### Delete Catalog Item ```bash DELETE /klaviyo/api/catalog-items/{catalog_item_id} ``` #### Get Catalog Variants ```bash GET /klaviyo/api/catalog-variants ``` #### Get Catalog Categories ```bash GET /klaviyo/api/catalog-categories ``` ### Tags Organize resources with tags. #### Get Tags ```bash GET /klaviyo/api/tags ``` **Example:** ```bash python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://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 ```bash POST /klaviyo/api/tags ``` #### Update a Tag ```bash PATCH /klaviyo/api/tags/{tag_id} ``` #### Delete a Tag ```bash DELETE /klaviyo/api/tags/{tag_id} ``` #### Tag a Campaign ```bash POST /klaviyo/api/tag-campaign-relationships ``` #### Tag a Flow ```bash POST /klaviyo/api/tag-flow-relationships ``` #### Get Tag Groups ```bash GET /klaviyo/api/tag-groups ``` **Example:** ```bash 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 ```bash POST /klaviyo/api/tag-groups ``` #### Update Tag Group ```bash PATCH /klaviyo/api/tag-groups/{tag_group_id} ``` #### Delete Tag Group ```bash DELETE /klaviyo/api/tag-groups/{tag_group_id} ``` ### Coupons Manage discount codes. #### Get Coupons ```bash GET /klaviyo/api/coupons ``` #### Create a Coupon ```bash POST /klaviyo/api/coupons ``` **Example:** ```bash python <<'EOF' import urllib.request, os, json data = json.dumps({'data': {'type': 'coupon', 'attributes': {'external_id': 'SUMMER_SALE_2024', 'description': 'Summer sale discount coupon'}}}).encode() req = urllib.request.Request('https://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 ```bash GET /klaviyo/api/coupon-codes ``` > **Note:** This endpoint requires a filter parameter. You must filter by coupon ID or profile ID. **Example:** ```bash python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://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 ```bash POST /klaviyo/api/coupon-codes ``` **Example:** ```bash python <<'EOF' import urllib.request, os, json data = json.dumps({'data': {'type': 'coupon-code', 'attributes': {'unique_code': 'SAVE20NOW', 'expires_at': '2025-12-31T23:59:59Z'}, 'relationships': {'coupon': {'data': {'type': 'coupon', 'id': 'SUMMER_SALE_2024'}}}}}).encode() req = urllib.request.Request('https://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 ```bash GET /klaviyo/api/webhooks ``` **Example:** ```bash 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 ```bash POST /klaviyo/api/webhooks ``` **Example:** ```bash python <<'EOF' import urllib.request, os, json data = json.dumps({'data': {'type': 'webhook', 'attributes': {'name': 'Order Placed Webhook', 'endpoint_url': 'https://example.com/webhooks/klaviyo', 'enabled': True}, 'relationships': {'webhook-topics': {'data': [{'type': 'webhook-topic', 'id': 'campaign:sent'}]}}}}).encode() req = urllib.request.Request('https://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 ```bash GET /klaviyo/api/webhooks/{webhook_id} ``` #### Update a Webhook ```bash PATCH /klaviyo/api/webhooks/{webhook_id} ``` #### Delete a Webhook ```bash DELETE /klaviyo/api/webhooks/{webhook_id} ``` #### Get Webhook Topics ```bash GET /klaviyo/api/webhook-topics ``` ### Accounts Retrieve account information. #### Get Accounts ```bash GET /klaviyo/api/accounts ``` **Example:** ```bash python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://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 ```bash GET /klaviyo/api/images ``` **Example:** ```bash 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 ```bash GET /klaviyo/api/images/{image_id} ``` #### Upload Image from URL ```bash POST /klaviyo/api/images ``` **Example:** ```bash 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 ```bash GET /klaviyo/api/forms ``` **Example:** ```bash 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 ```bash GET /klaviyo/api/forms/{form_id} ``` #### Get Form Versions ```bash GET /klaviyo/api/forms/{form_id}/form-versions ``` ### Reviews Manage product reviews. #### Get Reviews ```bash GET /klaviyo/api/reviews ``` **Example:** ```bash 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 ```bash GET /klaviyo/api/reviews/{review_id} ``` #### Update Review ```bash PATCH /klaviyo/api/reviews/{review_id} ``` ### Universal Content Manage reusable email content blocks. #### Get Universal Content ```bash GET /klaviyo/api/template-universal-content ``` **Example:** ```bash 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 ```bash POST /klaviyo/api/template-universal-content ``` #### Update Universal Content ```bash PATCH /klaviyo/api/template-universal-content/{content_id} ``` #### Delete Universal Content ```bash DELETE /klaviyo/api/template-universal-content/{content_id} ``` ### Bulk Profile Subscriptions Manage email/SMS subscriptions in bulk. #### Bulk Subscribe Profiles ```bash POST /klaviyo/api/profile-subscription-bulk-create-jobs ``` **Example:** ```bash python <<'EOF' import urllib.request, os, json data = json.dumps({ 'data': { 'type': [REDACTED_SECRET], 'attributes': { 'profiles': { 'data': [{ 'type': 'profile', 'attributes': { 'email': '[REDACTED_SECRET]', '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 ```bash POST /klaviyo/api/profile-subscription-bulk-delete-jobs ``` #### Bulk Suppress Profiles ```bash POST /klaviyo/api/profile-suppression-bulk-create-jobs ``` #### Bulk Unsuppress Profiles ```bash POST /klaviyo/api/profile-suppression-bulk-delete-jobs ``` ### Profile Bulk Import Import profiles in bulk. #### Get Bulk Import Jobs ```bash GET /klaviyo/api/profile-bulk-import-jobs ``` **Example:** ```bash 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 ```bash POST /klaviyo/api/profile-bulk-import-jobs ``` ## Filtering Klaviyo uses JSON:API filtering syntax. Common operators: | Operator | Example | |----------|---------| | `equals` | `filter=equals(email,"[REDACTED_SECRET]")` | | `contains` | `filter=contains(name,"newsletter")` | | `greater-than` | `filter=greater-than(datetime,2024-01-01T00:00:00Z)` | | `less-than` | `filter=less-than(created,2024-03-01)` | | `greater-or-equal` | `filter=greater-or-equal(updated,2024-01-01)` | | `any` | `filter=any(status,["draft","scheduled"])` | Combine filters with `and`: ``` filter=and(equals(status,"active"),greater-than(created,2024-01-01)) ``` ## Pagination Klaviyo uses cursor-based pagination: ```bash python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://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: ```json { "data": [...], "links": { "self": "https://a.klaviyo.com/api/profiles", "next": "https://a.klaviyo.com/api/profiles?page[cursor]=WzE2..." } } ``` ## Sparse Fieldsets Request only specific fields to reduce response size: ```bash # Request only email and first_name for profiles ?fields[profile]=email,first_name # Request specific fields for included relationships ?include=lists&fields[list]=name,created ``` ## Code Examples ### JavaScript ```javascript const response = await fetch( 'https://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 ```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: ```bash echo $MATON_API_KEY ``` 2. Verify the API key is valid by listing connections: ```bash python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://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](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:[REDACTED_SECRET])


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (CRITICAL)