How to Export Klaviyo Profiles and Events to JSON
Export Klaviyo profiles, list members or events (such as Placed Order or Opened Email) to a JSON file on a schedule, ready for a data warehouse, a backup or another tool.
What This Integration Does
Klaviyo exports lists and segments to CSV from its UI, but events, custom properties and anything you want on a schedule need the API. This Spojit workflow uses the Klaviyo API to read profiles (all of them, or those updated recently) or events of a given metric, follows Klaviyo's pagination to the end, flattens Klaviyo's JSON:API format into plain objects, and saves the result as a JSON file in your File Store or on an SFTP server.
Runs are incremental when you filter on updated for profiles or datetime for events, so a daily export contains only that day's changes. Each run writes a new dated file and nothing in Klaviyo is changed, so re-running is always safe.
Prerequisites
- A Klaviyo connection with a private API key that has read access to Profiles, Lists and Events.
- For event exports, the metric ID of the event (for example Placed Order). List metrics once with
raw-api-request,GET/metrics. - Optional: an FTP / SFTP connection for delivery.
Step 1: Schedule Trigger
Add a Trigger node with type Schedule, cron 0 3 * * *. Build the window start with a Date & Time subtract step that takes one day plus an hour of overlap off the trigger time. Name it since; the ISO 8601 timestamp is in {{ since.iso }}.
Step 2: Read Profiles or Events
Add a Connector node on Klaviyo in Direct Mode.
- Profiles:
list-profileswithfiltergreater-than(updated,{{ since.iso }}),sortupdatedandpageSize100. - Events:
list-eventswithfilterand(equals(metric_id,"YOUR_METRIC_ID"),greater-than(datetime,{{ since.iso }}))andsortdatetime. - One list's members:
raw-api-requestwithGET/lists/YOUR_LIST_ID/profiles.
Name the output page. Klaviyo returns up to 100 records and a links.next URL when there are more.
Step 3: Follow the Pagination
Wrap the call in a Loop in While mode that continues while links.next is present, passing the cursor from it into pageCursor. Collect each page's data array. A Max iterations of 500 (50,000 records) protects against runaway loops; raise it for very large accounts.
Step 4: Flatten Klaviyo's Format
Klaviyo wraps every record as { "type", "id", "attributes": { ... } }. Add a Transform with Iterate over set to the collected records to produce plain objects:
{
"id": "{{ item.id }}",
"email": "{{ item.attributes.email }}",
"phone_number": "{{ item.attributes.phone_number }}",
"first_name": "{{ item.attributes.first_name }}",
"last_name": "{{ item.attributes.last_name }}",
"created": "{{ item.attributes.created }}",
"updated": "{{ item.attributes.updated }}",
"properties": {{ item.attributes.properties }}
}
For events, map datetime, event_properties (which hold the order value, items and so on for Placed Order) and the related profile ID from relationships.profile.data.id.
Step 5: Save the JSON File
Add a Connector node on JSON Tools with stringify, then a File Store node with Save a file: Name klaviyo-profiles-{{ run_date.result }}.json, Content type application/json, If the name is taken Keep both. To deliver the file, add an FTP / SFTP step with upload-file.
Tips
- Full backup once, then increments: run once manually without the date filter for a full backup, then let the schedule export only changes.
- Consent fields: email and SMS consent live under
subscriptions, which Klaviyo only returns when requested. Useraw-api-requestwithadditional-fields[profile]=subscriptionsif your export needs them. - Load into a warehouse: the same flattened records can go straight into MySQL or MongoDB instead of a file; see the Snowflake tutorial in this help center for loading into Snowflake.
- Events are big: high-volume metrics such as Opened Email produce millions of rows. Export the metrics you analyse (Placed Order, Started Checkout) rather than everything.
Common Pitfalls
- Filter syntax: Klaviyo filters use its own syntax, such as
greater-than(updated,2026-10-01T00:00:00Z), with no quotes around dates. A malformed filter returns a 400 error with a hint. - Rate limits: Klaviyo limits requests per second per endpoint. Large exports should run off-peak; Spojit's step retries help with occasional 429 responses.
- Personal data: profile exports are personal data. Keep only fields you need and restrict access to the File Store folder or SFTP path.
- Time zones: Klaviyo timestamps are UTC with an offset. Build
sincein UTC too, or the window shifts by your offset.
Testing
Run the workflow manually with a one-hour window and check the file: the record count should match a Klaviyo segment filtered the same way, and every record should have an id and an email or phone number. Then turn on the schedule.