Agent skill
klaviyo-common-errors
Diagnose and fix common Klaviyo API errors and exceptions. Use when encountering Klaviyo 4xx/5xx errors, debugging failed requests, or troubleshooting SDK integration issues. Trigger with phrases like "klaviyo error", "fix klaviyo", "klaviyo not working", "debug klaviyo", "klaviyo 400", "klaviyo 429".
Install this agent skill to your Project
npx add-skill https://github.com/jeremylongshore/claude-code-plugins-plus-skills/tree/main/plugins/saas-packs/klaviyo-pack/skills/klaviyo-common-errors
SKILL.md
Klaviyo Common Errors
Overview
Quick reference for the most common Klaviyo API errors with real error payloads, root causes, and solutions.
Prerequisites
klaviyo-apiSDK installed- API credentials configured
- Access to application logs
Instructions
Step 1: Identify the Error
Klaviyo returns JSON:API error responses. Extract the status code and error detail:
try {
await profilesApi.createProfile(payload);
} catch (error: any) {
console.error('Status:', error.status);
console.error('Errors:', JSON.stringify(error.body?.errors, null, 2));
// error.body.errors[] has: { id, code, title, detail, source }
}
Step 2: Match and Fix
400 -- Bad Request (Validation Error)
Actual Klaviyo response:
{
"errors": [{
"id": "abc-123",
"code": "invalid",
"title": "Invalid input.",
"detail": "The email field is required.",
"source": { "pointer": "/data/attributes/email" }
}]
}
Common causes:
- Missing required field (email, metric name, list name)
- Invalid phone number format (must be E.164:
+15551234567) - Invalid filter syntax in query params
- Wrong
typevalue in JSON:API payload - Sending
snake_caseinstead ofcamelCase(SDK uses camelCase)
Fix:
// Wrong: snake_case
{ first_name: 'Jane', phone_number: '+155...' }
// Right: camelCase (SDK convention)
{ firstName: 'Jane', phoneNumber: '+15551234567' }
401 -- Unauthorized
Actual response:
{
"errors": [{
"code": "not_authenticated",
"title": "Authentication credentials were not provided.",
"detail": "Missing or invalid Authorization header."
}]
}
Root causes:
- Missing
KLAVIYO_PRIVATE_KEYenvironment variable - Using a public key (6 chars) instead of private key (
pk_*) - API key was revoked or rotated
Fix:
# Verify key is set and starts with pk_
echo $KLAVIYO_PRIVATE_KEY | head -c 3
# Should print: pk_
# Test with cURL
curl -s -w "%{http_code}" -o /dev/null \
-H "Authorization: Klaviyo-API-Key $KLAVIYO_PRIVATE_KEY" \
-H "revision: 2024-10-15" \
"https://a.klaviyo.com/api/accounts/"
403 -- Forbidden (Missing Scope)
Actual response:
{
"errors": [{
"code": "permission_denied",
"title": "You do not have permission to perform this action.",
"detail": "The API key does not have the required scope: profiles:write"
}]
}
Fix: Generate a new API key with the required scope at Settings > API Keys > Create Private API Key.
| Endpoint | Required Scope |
|---|---|
POST /api/profiles/ |
profiles:write |
GET /api/segments/ |
segments:read |
POST /api/events/ |
events:write |
POST /api/campaigns/ |
campaigns:write |
POST /api/data-privacy-deletion-jobs/ |
data-privacy:write |
404 -- Not Found
Typical causes:
- Wrong resource ID (profile, list, segment, campaign)
- Using v1/v2 URL paths instead of new API (
/api/v2/is dead, use/api/) - Resource was deleted
Fix:
// Verify the resource exists first
const lists = await listsApi.getLists();
const targetList = lists.body.data.find(l => l.attributes.name === 'Newsletter');
if (!targetList) throw new Error('List not found');
409 -- Conflict (Duplicate)
Actual response:
{
"errors": [{
"code": "duplicate",
"title": "Conflict.",
"detail": "A profile already exists with the email customer@example.com"
}]
}
Fix: Use createOrUpdateProfile (upsert) instead of createProfile:
// This handles both create and update
await profilesApi.createOrUpdateProfile({
data: {
type: 'profile' as any,
attributes: { email: 'customer@example.com', firstName: 'Updated' },
},
});
429 -- Rate Limited
Headers on 429 response:
Retry-After: 10
Klaviyo rate limits (per-account, fixed window):
| Window | Limit |
|---|---|
| Burst (1 second) | 75 requests |
| Steady (1 minute) | 700 requests |
Note: When rate limited, RateLimit-Remaining and RateLimit-Reset headers are NOT returned. Only Retry-After (integer seconds) is present.
Fix: Honor Retry-After header:
catch (error: any) {
if (error.status === 429) {
const retryAfter = parseInt(error.headers?.['retry-after'] || '10');
console.log(`Rate limited. Waiting ${retryAfter}s...`);
await new Promise(r => setTimeout(r, retryAfter * 1000));
// Retry the request
}
}
500/503 -- Klaviyo Server Error
Fix:
- Check Klaviyo Status Page
- Retry with exponential backoff (see
klaviyo-rate-limits) - If persistent, check Klaviyo's changelog for known issues
Common SDK-Level Errors
| Error | Cause | Fix |
|---|---|---|
Cannot find module 'klaviyo-api' |
Wrong package | npm install klaviyo-api (not @klaviyo/sdk) |
TypeError: ... is not a constructor |
Wrong import | Use new ProfilesApi(session) not new KlaviyoClient() |
response.data is undefined |
Wrong access pattern | Use response.body.data (not response.data) |
filter is not valid |
Bad filter syntax | Use equals(field,"value") not field = value |
Quick Diagnostic Commands
# Check Klaviyo API health
curl -s -o /dev/null -w "%{http_code}" \
-H "Authorization: Klaviyo-API-Key $KLAVIYO_PRIVATE_KEY" \
-H "revision: 2024-10-15" \
"https://a.klaviyo.com/api/accounts/"
# Check Klaviyo status page
curl -s https://status.klaviyo.com/api/v2/status.json | python3 -m json.tool
# Verify local env
env | grep KLAVIYO
npm list klaviyo-api
Escalation Path
- Collect evidence with
klaviyo-debug-bundle - Check status.klaviyo.com
- Open ticket at Klaviyo Support with request IDs from error responses
Resources
Next Steps
For comprehensive debugging, see klaviyo-debug-bundle.
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
dockerfile-generator
Dockerfile Generator - Auto-activating skill for DevOps Basics. Triggers on: dockerfile generator, dockerfile generator Part of the DevOps Basics skill category.
branch-naming-helper
Branch Naming Helper - Auto-activating skill for DevOps Basics. Triggers on: branch naming helper, branch naming helper Part of the DevOps Basics skill category.
readme-generator
Readme Generator - Auto-activating skill for DevOps Basics. Triggers on: readme generator, readme generator Part of the DevOps Basics skill category.
makefile-generator
Makefile Generator - Auto-activating skill for DevOps Basics. Triggers on: makefile generator, makefile generator Part of the DevOps Basics skill category.
gitignore-generator
Gitignore Generator - Auto-activating skill for DevOps Basics. Triggers on: gitignore generator, gitignore generator Part of the DevOps Basics skill category.
pre-commit-hook-setup
Pre Commit Hook Setup - Auto-activating skill for DevOps Basics. Triggers on: pre commit hook setup, pre commit hook setup Part of the DevOps Basics skill category.
Didn't find tool you were looking for?