Klaviyo Events API: send custom events safely
Short answer. Define the event and identity contract before coding. Send server-authoritative events to
POST https://a.klaviyo.com/api/eventswith least-privilege authentication and a supportedrevisionheader. Include a stableunique_idfor idempotent retries, the actual eventtime, structured properties, and a profile identifier. Treat202 Acceptedas queued, handle429withRetry-After, monitor ingestion, and usebackfill: truefor historical replays that must not trigger flows.
Custom events let Klaviyo respond to product, subscription, account, marketplace, offline, or operational behavior that a native integration does not provide. The API call is the easy part. Reliable identity, semantics, retries, monitoring, and lifecycle ownership determine whether the event can safely trigger customer communication.
This guide was reviewed July 16, 2026 against Klaviyo's official Events API overview, Create Event reference, rate-limit guide, and versioning policy. Always use the current reference for production code.
Start with an event contract
Create a tracking plan before an endpoint integration.
| Field | Example | Decision |
|---|---|---|
| Metric name | Report Generated |
Stable business meaning |
| Trigger moment | Report persisted successfully | Not button click or attempt |
| Profile identity | Internal user ID | Stable across email changes |
| Object context | workspace_id | Account or project relationship |
| Event time | Source occurrence in UTC | Not API delivery time |
| Unique ID | Source event UUID | Stable across retries |
| Required properties | report_type, project_id | Used by flow or analysis |
| Optional properties | source, template | Safe fallback if missing |
| Owner | Product data team | Monitors schema and delivery |
| Lifecycle uses | Activation flow, segment | Downstream dependencies |
An event name should describe something that happened. Use Subscription Canceled, not Subscription Status, and define whether it occurs when cancellation is requested or becomes effective.
Avoid changing semantics behind an existing metric. If the event meaning changes materially, version the source contract or create a new metric after a migration plan.
Event versus profile property
Events record occurrences with time and context. Profile properties represent current person-level state.
For a subscription:
- event:
Subscription Started,Renewal Failed,Subscription Paused; - profile property:
current_subscription_status = active; - event property: subscription ID, plan, amount, currency, failure reason.
Flows often need both. The trigger event provides immutable context, while the current profile state can stop a later message after the situation changes.
Be cautious about update order. If the event reaches Klaviyo before a related profile update, a flow can evaluate stale state. Include essential context on the event or sequence the operations with tested behavior.
Choose a stable profile identity
The current Create Event endpoint requires at least one profile identifier such as Klaviyo profile ID, email, or phone number. Prefer a stable internal identifier or mapped Klaviyo ID where the architecture supports it. Email addresses change and can create identity fragmentation.
Document:
- source user or customer ID;
- mapping to Klaviyo profile;
- anonymous-to-known behavior;
- email and phone changes;
- guest checkout identity;
- merge, duplicate, and deletion handling;
- account or object relationship.
Do not use test domains such as example.com or test.com to validate ingestion. Klaviyo's current Events API documentation says events with those test-style addresses can return 202 and then be silently dropped. Use a controlled domain you own and safe test profiles.
Authenticate with least privilege
For a private integration, use a private API key with only the scopes required by the endpoints. Creating events currently requires events:write.
Security controls:
- store the key in a secret manager;
- never expose a private key in browser or mobile code;
- use separate credentials by environment and integration;
- restrict access to deployment identities;
- rotate and revoke keys through a documented process;
- never log authorization headers;
- alert on unexpected usage.
For a multi-account product integration, evaluate OAuth and its separate rate-limit behavior rather than asking every customer to paste unrestricted keys.
Pin an API revision
Klaviyo versions modern APIs with date-based revision headers. Pass a supported revision such as the exact date selected from the current reference. Do not copy the example date in this article as a permanent value.
Pinning provides predictable request and response behavior. Maintain:
- current pinned revision;
- reference and changelog links;
- upgrade owner;
- contract tests against the next revision;
- deprecation review cadence.
Klaviyo's versioning policy marks beta revisions with a .pre suffix and says they should not be used in production. Use stable revisions for customer-facing systems.
Structure the Create Event request
The endpoint currently follows JSON:API conventions. Conceptually, send:
{
"data": {
"type": "event",
"attributes": {
"metric": {
"data": {
"type": "metric",
"attributes": { "name": "Project Published" }
}
},
"profile": {
"data": {
"type": "profile",
"attributes": { "email": "qa@your-owned-domain.com" }
}
},
"properties": {
"project_id": "prj_123",
"workspace_id": "ws_456",
"template": "weekly-report"
},
"time": "2026-07-16T09:30:00Z",
"unique_id": "90974d0d-5d62-4d78-98ee-450d74cd7090"
}
}
}
Use the exact current API reference and SDK types because shape and supported fields can evolve.
Use unique_id for idempotency
Klaviyo currently deduplicates events using profile, metric, and unique_id. Generate a stable unique identifier for each logical source event and reuse the same value on every retry.
Good source IDs:
- immutable order or transaction event ID;
- message ID from an event bus;
- UUID stored with the source record;
- deterministic ID from a truly unique business occurrence.
Do not generate a new UUID on every retry because that defeats idempotency. Do not reuse an order ID across multiple different order events without including event type or source occurrence.
The current documentation warns that, without unique_id, events for the same profile and metric in the same second can collide because the default is derived from the timestamp. Always provide it for production event sources.
Send the actual occurrence time
Set time to when the source action occurred, not when a retry worker delivered it. This keeps event history and time-based analysis accurate.
Use an ISO 8601 timestamp with an explicit time zone, commonly UTC. Validate impossible future dates and stale source clocks.
For delayed events, decide whether the lifecycle should still trigger. A payment failure delivered six hours late may need different handling. Event timestamp accuracy does not automatically prevent a flow from acting on stale data, so use eligibility filters or freshness properties.
Keep properties useful and bounded
Event properties should support flow content, segmentation, debugging, and analysis. Examples:
- stable object IDs;
- product or plan name;
- amount and currency;
- reason code with controlled values;
- destination URL built safely;
- market or locale;
- event schema version.
Avoid sending full internal objects, large HTML, secrets, payment data, or unused personal information. Klaviyo documents payload, property count, string, array, nesting, and timestamp limits. Treat the current API reference as the authority.
Use controlled property names and types. A property that is sometimes number and sometimes string makes segmentation unreliable.
Place only truly non-segmentable large context into fields designed for that purpose, and still minimize it. Customer messaging systems are not data lakes.
Treat 202 as queued, not fully processed
The Create Event endpoint currently responds 202 Accepted after validation and submission for processing. Klaviyo explicitly says that success does not guarantee processing is complete.
Your producer should record:
- source event ID;
- request time and attempt;
- endpoint revision;
- response status;
- final retry or dead-letter state;
- a correlation value that does not expose personal data.
For critical integrations, reconcile source events with Klaviyo event retrieval or profile activity samples, taking processing latency into account. Do not perform a read immediately and declare failure when the pipeline is asynchronous.
Handle errors and rate limits
Classify responses:
- 2xx: accepted according to endpoint semantics;
- 400 or 422-style validation: fix payload or schema, do not retry blindly;
- 401 or 403: credential, scope, or authorization issue;
- 404: endpoint, resource, or revision issue;
- 429: rate limit, honor
Retry-After; - 5xx and network timeout: retry with bounded exponential backoff and jitter.
Klaviyo uses burst and steady windows, with endpoint-specific limits published in the reference. Non-429 responses can include rate-limit headers. A 429 currently replaces those with Retry-After.
Use a queue, concurrency control, exponential backoff, jitter, and a dead-letter path. Keep the same unique_id through retries. Do not hammer the endpoint after an outage.
Alert on sustained error rate, dead-letter depth, delivery latency, and unknown validation errors.
Use bulk endpoints for appropriate volume
When backfilling or sending high event volume, review current bulk endpoint behavior and limits. Batch by operational size, retain individual source IDs, and handle partial or whole-request validation according to the reference.
Do not use live flow-triggering events for a historical replay without a lifecycle plan. A backfill of past orders can send years of post-purchase email.
Use backfill: true for historical replay
Klaviyo's current Events API supports a backfill boolean for historical data. With backfill: true, the event remains available in event data and segmentation but does not trigger flows.
Use it when:
- migrating historical orders;
- replaying corrected past events;
- rebuilding data after an integration gap where customer messages should not fire;
- importing CRM history for analytics.
Use time and stable unique_id as well. Test backfill in a safe account or profile before a large import. Confirm downstream reporting and segmentation behavior matches the current documentation.
If some missed events should trigger a customer action, do not remove backfill protection globally. Create an explicit recovery audience and communication plan with freshness, consent, and customer relevance checks.
Design flow safety around events
An API event should not have unrestricted power to send.
Add flow controls:
- trigger filters for valid event properties;
- profile and channel eligibility;
- event freshness where relevant;
- current-state filter before delayed messages;
- cancellation or success exit;
- frequency and re-entry rules;
- fallback for missing content;
- internal notification on suspicious payload;
- manual mode during initial validation.
Use a synthetic or controlled event to test every branch. Then run a small production cohort before broad live status.
Monitoring and reconciliation
Create dashboards for:
- source events created;
- accepted requests;
- response codes by class;
- retry and dead-letter volume;
- end-to-end latency;
- Klaviyo metric volume;
- missing or unknown property rate;
- distinct profiles;
- flow entries and exits;
- downstream delivery and conversion.
Compare by hour and day with expected seasonality. Alert on both drop and spike. A tenfold event increase can be a duplicate bug even if every API response is successful.
Maintain a runbook with key rotation, revision upgrade, replay procedure, flow pause, event source owner, and incident contacts.
Implementation test plan
- Valid event for an existing controlled profile.
- Valid event that creates or updates a permitted profile attribute, if used.
- Duplicate retry with the same
unique_id. - Two legitimate events in the same second with different IDs.
- Missing required property.
- Wrong type and unknown enum value.
- Network timeout followed by safe retry.
- Simulated or controlled 429 handling.
- Historical event with
backfill: true. - Profile unsubscribed or suppressed for the target channel.
- Conversion or cancellation during a flow delay.
- Event volume spike and alert.
Verify the event in Klaviyo, flow behavior, message preview, logs, and downstream reports. Do not use only the HTTP response as QA evidence.
FAQ
What endpoint creates a Klaviyo event?
The current endpoint is POST https://a.klaviyo.com/api/events. Use the official current reference, required authentication, supported revision, and JSON:API payload.
Why did I receive 202 but not see the event?
202 means accepted for asynchronous processing, not guaranteed complete. Allow processing time, verify identity and payload, check test-domain restrictions, deduplication, logs, and the current status page.
How do I prevent duplicate Klaviyo events?
Provide a stable unique_id per logical event and reuse it on retries. Klaviyo currently deduplicates by profile, metric, and unique ID.
How should I import historical events?
Provide the original time, stable IDs, and use backfill: true when the replay must not trigger flows. Test a small batch and reconcile counts.
How should 429 errors be retried?
Honor Retry-After, queue requests, and use bounded backoff with jitter. Respect the endpoint's burst and steady limits and preserve idempotency.
Make custom events dependable enough to trigger customers
Deliver defines event contracts, implements reliable ingestion, and validates lifecycle behavior from source system to message. Request a Klaviyo Events API implementation review.
Want to apply this to your stack?
Spend 30 minutes with Charlotte to review your CRM setup, size the opportunity and leave with a practical action plan.
Book a 30-minute call →