Introduction
# 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://gateway.maton.ai/klaviyo/api/profiles') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('revision', '2024-10-15') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
## Base URL
``` https://gateway.maton.ai/klaviyo/{native-api-path} ```
Replace `{native-api-path}` with the actual Klaviyo API endpoint path. The gateway proxies requests to `a.klaviyo.com` and automatically injects your OAuth token.
## Authentication
All requests require the Maton API key in the Authorization header:
``` Authorization: Bearer $MATON_API_KEY ```
**Environment Variable:** Set your API key as `MATON_API_KEY`:
```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: 2024-10-15 ```
## Connection Management
Manage your Klaviyo OAuth connections at `https://ctrl.maton.ai`.
### List Connections
```bash 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
```bash 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
```bash 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:** ```json { "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
```bash 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:
```bash python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://gateway.maton.ai/klaviyo/api/profiles') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('revision', '2024-10-15') req.add_header('Maton-Connection', '21fd90f9-5935-43cd-b6c8-bde9d915ca80') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
If omitted, the gateway uses the default (oldest) active connection.
## API Reference
### Profiles
Manage customer data and consent.
#### Get Profiles
```bash GET /klaviyo/api/profiles ```
Query parameters: - `filter` - Filter profiles (e.g., `filter=equals(email,"[email protected]")`) - `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://gateway.maton.ai/klaviyo/api/profiles?fields[profile]=email,first_name,last_name&page[size]=10') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('revision', '2024-10-15') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
**Response:** ```json { "data": [ { "type": "profile", "id": "01GDDKASAP8TKDDA2GRZDSVP4H", "attributes": { "email": "[email protected]", "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://gateway.maton.ai/klaviyo/api/profiles/01GDDKASAP8TKDDA2GRZDSVP4H') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('revision', '2024-10-15') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
#### Create a Profile
```bash POST /klaviyo/api/profiles Content-Type: application/json
{ "data": { "type": "profile", "attributes": { "email": "[email protected]", "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': '[email protected]', 'first_name': 'John', 'last_name': 'Doe'}}}).encode() req = urllib.request.Request('https://gateway.maton.ai/klaviyo/api/profiles', data=data, method='POST') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('Content-Type', 'application/json') req.add_header('revision', '2024-10-15') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
#### Update a Profile
```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://gateway.maton.ai/klaviyo/api/profiles/01GDDKASAP8TKDDA2GRZDSVP4H', data=data, method='PATCH') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('Content-Type', 'application/json') req.add_header('revision', '2024-10-15') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
#### Merge Profiles
```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://gateway.maton.ai/klaviyo/api/lists?fields[list]=name,created,updated') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('revision', '2024-10-15') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
**Response:** ```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://gateway.maton.ai/klaviyo/api/lists', data=data, method='POST') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('Content-Type', 'application/json') req.add_header('revision', '2024-10-15') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
#### Update a List
```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://gateway.maton.ai/klaviyo/api/lists/Y6nRLr/relationships/profiles', data=data, method='POST') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('Content-Type', 'application/json') req.add_header('revision', '2024-10-15') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
#### Remove Profiles from List
```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://gateway.maton.ai/klaviyo/api/segments?fields[segment]=name,created,updated') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('revision', '2024-10-15') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
#### Get a Segment
```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 ```
Query parameters: - `filter` - Filter campaigns (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://gateway.maton.ai/klaviyo/api/campaigns?filter=equals(messages.channel,"email")') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('revision', '2024-10-15') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
**Response:** ```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://gateway.maton.ai/klaviyo/api/campaigns', data=data, method='POST') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('Content-Type', 'application/json') req.add_header('revision', '2024-10-15') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
#### Update a Campaign
```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://gateway.maton.ai/klaviyo/api/flows?fields[flow]=name,status,created,updated') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('revision', '2024-10-15') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
**Response:** ```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://gateway.maton.ai/klaviyo/api/flows/VJvBNr', data=data, method='PATCH') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('Content-Type', 'application/json') req.add_header('revision', '2024-10-15') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
#### Delete a Flow
```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://gateway.maton.ai/klaviyo/api/events?filter=greater-than(datetime,2024-01-01T00:00:00Z)&page[size]=50') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('revision', '2024-10-15') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
**Response:** ```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': '[email protected]'}}}, 'metric': {'data': {'type': 'metric', 'attributes': {'name': 'Viewed Product'}}}, 'properties': {'product_id': 'SKU123', 'product_name': 'Blue T-Shirt', 'price': 29.99}}}}).encode() req = urllib.request.Request('https://gateway.maton.ai/klaviyo/api/events', data=data, method='POST') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('Content-Type', 'application/json') req.add_header('revision', '2024-10-15') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
#### Bulk Create Events
```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://gateway.maton.ai/klaviyo/api/metrics') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('revision', '2024-10-15') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
**Response:** ```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://gateway.maton.ai/klaviyo/api/metric-aggregates', data=data, method='POST') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('Content-Type', 'application/json') req.add_header('revision', '2024-10-15') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
### Templates
Manage email templates.
#### Get Templates
```bash GET /klaviyo/api/templates ```
**Example:**
```bash python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://gateway.maton.ai/klaviyo/api/templates?fields[template]=name,created,updated') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('revision', '2024-10-15') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
#### Get a Template
```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://gateway.maton.ai/klaviyo/api/templates', data=data, method='POST') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('Content-Type', 'application/json') req.add_header('revision', '2024-10-15') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
#### Update a Template
```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://gateway.maton.ai/klaviyo/api/catalog-items?fields[catalog-item]=title,price,url') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('revision', '2024-10-15') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
**Response:** ```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://gateway.maton.ai/klaviyo/api/tags') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('revision', '2024-10-15') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
#### Create a Tag
```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 ```
### 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://gateway.maton.ai/klaviyo/api/coupons', data=data, method='POST') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('Content-Type', 'application/json') req.add_header('revision', '2024-10-15') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
> **Note:** The `external_id` must match regex `^[0-9_A-z]+$` (alphanumeric and underscores only, no hyphens).
#### Get Coupon Codes
```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://gateway.maton.ai/klaviyo/api/coupon-codes?filter=equals(coupon.id,"SUMMER_SALE_2024")') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('revision', '2024-10-15') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
#### Create Coupon Codes
```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://gateway.maton.ai/klaviyo/api/coupon-codes', data=data, method='POST') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('Content-Type', 'application/json') req.add_header('revision', '2024-10-15') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
### Webhooks
Configure event notifications.
#### Get Webhooks
```bash GET /klaviyo/api/webhooks ```
**Example:**
```bash python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://gateway.maton.ai/klaviyo/api/webhooks') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('revision', '2024-10-15') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
#### Create Webhook
```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://gateway.maton.ai/klaviyo/api/webhooks', data=data, method='POST') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('Content-Type', 'application/json') req.add_header('revision', '2024-10-15') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
#### Get a Webhook
```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://gateway.maton.ai/klaviyo/api/accounts') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('revision', '2024-10-15') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
## Filtering
Klaviyo uses JSON:API filtering syntax. Common operators:
| Operator | Example | |----------|---------| | `equals` | `filter=equals(email,"[email protected]")` | | `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://gateway.maton.ai/klaviyo/api/profiles?page[size]=50&page[cursor]=CURSOR_TOKEN') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('revision', '2024-10-15') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
Response includes pagination links:
```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://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
```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 `revision` header for API versioning (recommended: `2024-10-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://ctrl.maton.ai/connections') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
### Troubleshooting: Invalid App Name
1. Ensure your URL path starts with `klaviyo`. For example:
- Correct: `https://gateway.maton.ai/klaviyo/api/profiles` - Incorrect: `https://gateway.maton.ai/api/profiles`
## Resources
- [Klaviyo API Documentation](https://developers.klaviyo.com) - [API Reference](https://developers.klaviyo.com/en/reference/api_overview) - [Klaviyo Developer Portal](https://developers.klaviyo.com/en) - [Maton Community](https://discord.com/invite/dBfFAcefs2) - [Maton Support](mailto:[email protected])