Minimal working example: create a profile, track an event, and query the result using the klaviyo-api Node.js SDK against a.klaviyo.com/api/*.
klaviyo-install-auth setupKLAVIYO_PRIVATE_KEY set in environmentklaviyo-api package installed// hello-klaviyo.ts
import {
ApiKeySession,
ProfilesApi,
EventsApi,
ProfileCreateQuery,
ProfileEnum,
EventCreateQueryV2,
EventEnum,
} from 'klaviyo-api';
const session = new ApiKeySession(process.env.KLAVIYO_PRIVATE_KEY!);
const profilesApi = new ProfilesApi(session);
const eventsApi = new EventsApi(session);
// Create or update a profile
// NOTE: SDK uses camelCase (firstName, not first_name)
const profilePayload: ProfileCreateQuery = {
data: {
type: ProfileEnum.Profile,
attributes: {
email: 'hello@example.com',
firstName: 'Hello',
lastName: 'World',
properties: {
source: 'hello-world-script',
signupDate: new Date().toISOString(),
},
},
},
};
const profile = await profilesApi.createProfile(profilePayload);
console.log('Profile created:', profile.body.data.id);
// Track a custom event tied to the profile
const eventPayload: EventCreateQueryV2 = {
data: {
type: EventEnum.Event,
attributes: {
// The metric name -- creates the metric if it doesn't exist
metric: {
data: {
type: 'metric',
attributes: {
name: 'Hello World Test',
},
},
},
// Link to the profile by email
profile: {
data: {
type: ProfileEnum.Profile,
attributes: {
email: 'hello@example.com',
},
},
},
properties: {
message: 'First event from API!',
timestamp: new Date().toISOString(),
},
time: new Date().toISOString(),
value: 0,
},
},
};
await eventsApi.createEvent(eventPayload);
console.log('Event tracked: Hello World Test');
// Fetch profiles filtered by email
const profiles = await profilesApi.getProfiles({
filter: 'equals(email,"hello@example.com")',
});
const p = profiles.body.data[0];
console.log(`Found: ${p.attributes.firstName} ${p.attributes.lastName}`);
console.log(`ID: ${p.id}`);
console.log(`Created: ${p.attributes.created}`);
// hello-klaviyo.ts -- full runnable script
import {
ApiKeySession,
ProfilesApi,
EventsApi,
ProfileEnum,
} from 'klaviyo-api';
async function main() {
const session = new ApiKeySession(process.env.KLAVIYO_PRIVATE_KEY!);
const profilesApi = new ProfilesApi(session);
const eventsApi = new EventsApi(session);
// 1. Create profile
const profile = await profilesApi.createProfile({
data: {
type: ProfileEnum.Profile,
attributes: {
email: 'hello@example.com',
firstName: 'Hello',
lastName: 'World',
},
},
});
console.log(`Profile created: ${profile.body.data.id}`);
// 2. Track event
await eventsApi.createEvent({
data: {
type: 'event',
attributes: {
metric: { data: { type: 'metric', attributes: { name: 'Hello World Test' } } },
profile: { data: { type: 'profile', attributes: { email: 'hello@example.com' } } },
properties: { source: 'hello-world' },
time: new Date().toISOString(),
},
},
});
console.log('Event tracked successfully');
// 3. Query profile back
const result = await profilesApi.getProfiles({
filter: 'equals(email,"hello@example.com")',
});
console.log(`Verified: ${result.body.data[0]?.attributes.firstName}`);
}
main().catch(console.error);
Run it:
npx tsx hello-klaviyo.ts
Profile created: 01JXXXXXXXXXXXXXXXXXXXXXX
Event tracked successfully
Verified: Hello
| Error | Status | Cause | Solution |
|---|---|---|---|
Duplicate profile |
409 | Email already exists | Use createOrUpdateProfile instead |
Invalid email format |
400 | Malformed email | Validate email before sending |
Missing metric name |
400 | Empty metric object | Always include metric.data.attributes.name |
Unauthorized |
401 | Bad API key | Check KLAVIYO_PRIVATE_KEY env var |
firstName, phoneNumber, lastName (not snake_case){ data: { type, attributes } } structureresponse.body.data (not response.data)email, phoneNumber, or externalId to identify profilesProceed to klaviyo-local-dev-loop for development workflow setup, or klaviyo-core-workflow-a for profile and list management.