[deliver]
Deliver article · 2026-07-16 · Charlotte Rodrigues

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/events with least-privilege authentication and a supported revision header. Include a stable unique_id for idempotent retries, the actual event time, structured properties, and a profile identifier. Treat 202 Accepted as queued, handle 429 with Retry-After, monitor ingestion, and use backfill: true for 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 on November 3, 2026 against Klaviyo's official Events API overview, Create Event reference, rate-limit guide, versioning policy, and authentication guide, all reopened that day. 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:

Flows often need both. The trigger event provides immutable context, while the current profile state can stop a later message after the situation changes.

In our reading, update order matters: 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:

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:

For a product integration used by many Klaviyo accounts, Klaviyo's authentication guide recommends OAuth for tech partners and lists improved rate limits among its benefits. In our reading, that is a better fit than asking every customer to paste a private key.

Server-side API or Klaviyo.js

Klaviyo's authentication guide separates two families. Server-side /api endpoints use a private key (prefix pk_, sent as Authorization: Klaviyo-API-Key your-private-api-key) and should be handled on your server. Client-side /client endpoints use the public key, your 6-character company ID (also called site ID), which cannot access secure data in your account. To manage keys, you need an Owner, Admin or Manager role (Settings, then API keys).

Klaviyo's JavaScript API exposes klaviyo.identify (set properties on a person, with an email or, for SMS-only contacts, a phone number) and klaviyo.track (record an event for an identified user). In our reading, browser events such as Viewed Product fit Klaviyo.js, while events produced by your backend (order confirmation, plan change) fit the server-side API. If the same action is sent from both, define which one owns the event: the browser event and the server event are separate unless they share profile, metric and unique_id.

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:

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 request body nests data, type and attributes, as in the examples of the Events API overview. 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:

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. 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, as in Klaviyo's examples (+00:00). The rate-limit guide lists event timestamps between 1990 and "now" plus one year as the accepted range, so validate impossible 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:

Avoid sending full internal objects, large HTML, secrets, payment data, or unused personal information. Klaviyo's rate-limit guide lists 400 event properties per data packet, 100 kB per field, 4,000 items per array and 11 levels of nested objects. Values of 0, null and an empty string are ignored when setting event properties, so they cannot be used for segmentation. 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:

Klaviyo's troubleshooting section says events are created asynchronously and can take up to a few minutes to appear in the interface or in the Get Events API. For critical integrations, reconcile source events with Klaviyo event retrieval or profile activity samples, taking that latency into account. Do not perform a read immediately and declare failure when the pipeline is asynchronous.

Handle errors and rate limits

Classify responses:

Klaviyo uses a burst window (1 second) and a steady window (1 minute), with endpoint-specific limits published in the reference. At the time of review, the Create Event page shows burst 350/s and steady 3,500/m. Non-429 responses carry rate-limit headers, and a 429 replaces them with a Retry-After header. The guide adds that immediate retries always receive a 429.

Klaviyo recommends watching for 429 and 503 and retrying with an exponential backoff that includes some randomness. Retry only after the Retry-After delay has expired. In our reading, a queue, concurrency control and a dead-letter path complete that approach. Keep the same unique_id through retries.

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 the Bulk Create Events reference (POST /api/event-bulk-create-jobs). At the time of review it accepts up to 1,000 events and 5 MB per request, with burst 10/s and steady 150/m. Retain individual source IDs: repeated unique_id values inside one bulk request return a 400 and none of the events in that request are processed.

Do not use live flow-triggering events for a historical replay without a lifecycle plan. Klaviyo warns that replaying past events can re-fire flows and send messages to profiles who already received them.

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:

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.

Outgoing webhooks from a flow

Sending events to Klaviyo and receiving data from Klaviyo are two different mechanisms. Klaviyo's flow webhook guide describes the webhook action: when a profile reaches that action in a flow, Klaviyo sends a POST request to the URL you configure, with the payload you wrote. The developer guide adds the conditions:

A flow webhook is not a two-way sync: it does not bring data from your system back into Klaviyo. For that, use the Events API described above.

Design flow safety around events

An API event should not have unrestricted power to send.

Add flow controls:

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:

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

  1. Valid event for an existing controlled profile.
  2. Valid event that creates or updates a permitted profile attribute, if used.
  3. Duplicate retry with the same unique_id.
  4. Two legitimate events in the same second with different IDs.
  5. Missing required property.
  6. Wrong type and unknown enum value.
  7. Network timeout followed by safe retry.
  8. Simulated or controlled 429 handling.
  9. Historical event with backfill: true.
  10. Profile unsubscribed or suppressed for the target channel.
  11. Conversion or cancellation during a flow delay.
  12. 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 the payload structure shown there.

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.

Provenance and verification

Check of 2026-11-03, pages reopened as raw HTML converted to text and read. Create Event reference (endpoint, burst 350/s and steady 3500/m, events:write scope, 202 meaning, revision header). Events API overview (unique_id idempotency, deduplication on profile, metric and unique_id, backfill, test-domain drop, 400 event properties, 1,000 events and 5 MB for bulk, 'up to a few minutes' for 202). Rate-limit guide (burst and steady windows, Retry-After, status codes, event limits table). Versioning policy (.pre beta revisions). Authentication guide (pk_ private keys, 6-character public key, OAuth). JavaScript API guide (identify and track). Flow webhook help article and developer guide (POST only, HTTPS URL, JSON body, flow-trigger events, MFA, retries, X-Klaviyo-Flow-ID).

Sources checked on
Reviewed by
Claude (AI review, Klaviyo developer documentation reopened and read on 2026-11-03)
AI assistance
Yes
Sources
  1. developers.klaviyo.com/en/reference/create_event
  2. developers.klaviyo.com/en/reference/events_api_overview
  3. developers.klaviyo.com/en/reference/bulk_create_events
  4. developers.klaviyo.com/en/docs/rate_limits_and_error_handling
  5. developers.klaviyo.com/en/docs/api_versioning_and_deprecation_policy
  6. developers.klaviyo.com/en/docs/authenticate_
  7. developers.klaviyo.com/en/docs/javascript_api
  8. help.klaviyo.com/hc/en-us/articles/4534329515931
  9. developers.klaviyo.com/en/docs/how_to_add_a_webhook_action_to_a_flow
Going further · Deliver sets up and runs Klaviyo for e-commerce brands: flows, campaigns and deliverability. See our Klaviyo agency page, or request a Klaviyo audit.
CR
Charlotte Rodrigues · CRM Lead at Deliver. Questions about this article? charlotte@agence-deliver.com

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 →