Skip to main content
RapidDev - Software Development Agency
retool-integrationsREST API Resource

How to Integrate Retool with Klaviyo

Connect Retool to Klaviyo by creating a REST API Resource with Klaviyo's base URL and private API key authentication. Use Klaviyo's v2 API to build email marketing operations panels that manage lists, view campaign performance, segment subscribers, and track flow analytics — giving your marketing and operations teams direct access to Klaviyo data without switching between tools.

What you'll learn

  • How to configure a Klaviyo REST API Resource in Retool with proper private key authentication
  • How to query Klaviyo profiles, lists, campaigns, and flows from the query editor
  • How to build an email marketing operations dashboard combining Klaviyo data with e-commerce order data
  • How to use JavaScript transformers to reshape Klaviyo's API response structure for Retool Tables
  • How to manage subscriber suppression and list membership from a Retool panel
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Intermediate14 min read25 minutesMarketingLast updated April 2026RapidDev Engineering Team
TL;DR

Connect Retool to Klaviyo by creating a REST API Resource with Klaviyo's base URL and private API key authentication. Use Klaviyo's v2 API to build email marketing operations panels that manage lists, view campaign performance, segment subscribers, and track flow analytics — giving your marketing and operations teams direct access to Klaviyo data without switching between tools.

Quick facts about this guide
FactValue
ToolKlaviyo
CategoryMarketing
MethodREST API Resource
DifficultyIntermediate
Time required25 minutes
Last updatedApril 2026

Build a Klaviyo Email Marketing Operations Panel in Retool

Klaviyo is the dominant email marketing platform in e-commerce, and teams using it quickly find that Klaviyo's built-in UI isn't optimized for operational tasks — looking up individual subscriber histories, bulk-managing list memberships, or combining campaign metrics with order data from your database. Retool bridges this gap by giving you direct query access to Klaviyo's API in a configurable internal tool.

With a Retool-Klaviyo integration, your marketing ops team can search subscribers by email or Klaviyo ID, view their full event history and list memberships, check campaign click rates alongside the segments that received each campaign, and identify high-value customers for VIP list management — all from a single panel. When combined with your e-commerce database in the same Retool app, you can join Klaviyo subscriber data with actual order data for a complete customer picture.

Klaviyo's API uses Bearer token authentication with a private API key that has configurable permissions. Retool's server-side proxy keeps this key secure. The most important operational use cases — subscriber management, campaign reporting, and flow monitoring — are all accessible through Klaviyo's v2 REST API with straightforward GET and POST queries.

Integration method

REST API Resource

Klaviyo connects to Retool through a REST API Resource using a private API key sent as a Bearer token in the Authorization header. All requests are proxied server-side through Retool, keeping your Klaviyo API key secure. You configure base URL and authentication once at the resource level, then build individual queries for each Klaviyo operation — list management, campaign metrics, profile lookup, and flow analytics.

Prerequisites

  • A Klaviyo account with a private API key (Settings → API Keys → Create Private API Key)
  • The private key should have read access to Profiles, Lists, Campaigns, and Flows
  • A Retool account with permission to create Resources
  • Familiarity with Retool's query editor and Table/Chart components
  • Optional: a connected e-commerce database to join with Klaviyo subscriber data

Step-by-step guide

1

Create a Klaviyo REST API Resource

Go to the Resources tab in your Retool instance and click Add Resource. Select REST API from the list of resource types. Name the resource 'Klaviyo API'. In the Base URL field, enter https://a.klaviyo.com. This is Klaviyo's API v2 base URL — all endpoint paths will be appended to this base. Do not include a trailing slash. Now configure authentication. Klaviyo uses Bearer token authentication with your private API key. In the Authentication section, select Bearer Token from the dropdown. In the Token field, enter your private API key — this is the long string starting with 'pk_' that you generated in Klaviyo's Settings → API Keys page. Alternatively, you can use a configuration variable to store the token securely. Navigate to Settings → Configuration Variables, create a variable named KLAVIYO_PRIVATE_KEY, mark it as Secret, and then in the Bearer Token field use {{ retoolContext.configVars.KLAVIYO_PRIVATE_KEY }} instead of the raw key value. Klaviyo's v2 API also requires a revision header. Add a header in the Default Headers section: key = revision, value = 2024-02-15 (or the latest API revision date). Click Save Changes.

Pro tip: Klaviyo's private API keys can have scoped permissions. Create a read-only key for your Retool reporting dashboard and a separate read-write key for management operations. Reference different configuration variables per query type for minimum-privilege access.

Expected result: A Klaviyo API REST resource is saved in your Resources list with Bearer token authentication and the revision header configured.

2

Query Klaviyo profiles and subscriber data

Create your first query to search for subscriber profiles. In your Retool app, open the Code panel and click the + icon to add a query. Name it searchProfiles and select the Klaviyo API resource. Set Method to GET. In the Path field, enter /api/profiles. Klaviyo's profiles endpoint supports filtering by email using the filter query parameter. Add a URL parameter: key = filter, value = equals(email,'{{ textInput_email.value }}'). This uses Klaviyo's filter syntax to find an exact email match. For browsing all profiles with pagination, use cursor-based pagination. Klaviyo v2 returns a next cursor in the response links.next field. Add a URL parameter: key = page[size], value = 50 to limit results per page. For lookup by Klaviyo profile ID, create a separate query named getProfileById with path /api/profiles/{{ textInput_profileId.value }} (GET, no body). After running the search query, you'll get a data array with profile objects. Each profile has attributes including email, first_name, last_name, phone_number, and a properties object with custom attributes set by your e-commerce platform.

transformer.js
1// JavaScript transformer — flatten Klaviyo profile response
2const profiles = (data.data || []);
3return profiles.map(profile => {
4 const attrs = profile.attributes || {};
5 return {
6 id: profile.id,
7 email: attrs.email || 'N/A',
8 first_name: attrs.first_name || '',
9 last_name: attrs.last_name || '',
10 phone_number: attrs.phone_number || 'N/A',
11 location: attrs.location
12 ? `${attrs.location.city || ''}, ${attrs.location.country || ''}`.trim()
13 : 'Unknown',
14 subscriptions: attrs.subscriptions?.email?.marketing?.consent || 'unknown',
15 created: attrs.created
16 ? new Date(attrs.created).toLocaleDateString()
17 : 'N/A',
18 // Custom properties stored in properties object
19 lifetime_value: attrs.properties?.lifetime_value
20 ? `$${attrs.properties.lifetime_value.toFixed(2)}`
21 : 'N/A'
22 };
23});

Pro tip: Klaviyo profile IDs are stable unique identifiers — store them alongside your customer records in your own database to make cross-system lookups faster. This avoids filtering large profile lists by email on every query.

Expected result: The searchProfiles query returns matching subscriber records. The transformer flattens the nested Klaviyo response into table-friendly rows with formatted property values.

3

Fetch campaign metrics and performance data

Create a query to retrieve campaign performance data. Name it getCampaigns. Set Method to GET, Path to /api/campaigns. Add a URL parameter: key = filter, value = equals(messages.channel,'email') to limit results to email campaigns only. Klaviyo's campaign endpoint returns campaign objects with basic metadata — name, status, created_at, send_time. To get actual performance metrics (opens, clicks, revenue), you need to use the campaign metrics endpoint. Create a second query named getCampaignMetrics with: - Method: GET - Path: /api/campaign-message-send-jobs/{{ table_campaigns.selectedRow.id }}/campaign-messages For aggregate campaign stats, use Klaviyo's reporting endpoint. Create a query named getCampaignReport: - Method: POST - Path: /api/campaign-values-reports - Body: JSON with the campaign ID and metric IDs for the stats you want Bind the getCampaigns query results to a Table component named table_campaigns. When a row is selected in table_campaigns, getCampaignMetrics automatically runs with the selected campaign ID, powering a detail panel. Add a Chart component showing open rate trends using the reporting endpoint data.

transformer.js
1// JavaScript transformer — format campaign list for display
2const campaigns = (data.data || []);
3return campaigns
4 .filter(c => c.attributes.status !== 'draft')
5 .map(campaign => {
6 const attrs = campaign.attributes || {};
7 return {
8 id: campaign.id,
9 name: attrs.name || 'Unnamed',
10 status: attrs.status || 'unknown',
11 send_time: attrs.send_time
12 ? new Date(attrs.send_time).toLocaleDateString('en-US', {
13 year: 'numeric', month: 'short', day: 'numeric'
14 })
15 : 'Not sent',
16 created_at: attrs.created_at
17 ? new Date(attrs.created_at).toLocaleDateString()
18 : 'N/A',
19 subject: attrs.campaign_messages?.[0]?.label || 'N/A'
20 };
21 })
22 .sort((a, b) => new Date(b.send_time) - new Date(a.send_time));
23

Pro tip: Klaviyo rate limits API calls to 75 requests per second for private API keys. If you're building a dashboard that loads many campaigns and their metrics simultaneously, chain the queries using event handlers rather than triggering them all in parallel.

Expected result: The getCampaigns query populates a table with sent campaigns sorted by send date. Selecting a row triggers the metrics query to load performance data for that specific campaign.

4

Build list management queries

Create queries to manage Klaviyo lists from Retool. First, create getLists (GET, /api/lists) to retrieve all lists with their names and profile counts. This powers a list selector dropdown in your app. Next, create getListProfiles to retrieve profiles in a selected list: - Method: GET - Path: /api/lists/{{ dropdown_list.value }}/profiles - URL parameter: page[size] = 100 For adding a profile to a list, create addProfileToList: - Method: POST - Path: /api/lists/{{ dropdown_list.value }}/relationships/profiles - Body: { "data": [{ "type": "profile", "id": "{{ textInput_profileId.value }}" }] } For removing a profile from a list, create removeProfileFromList: - Method: DELETE - Path: /api/lists/{{ dropdown_list.value }}/relationships/profiles - Body: { "data": [{ "type": "profile", "id": "{{ table_profiles.selectedRow.id }}" }] } Add a Dropdown component named dropdown_list with options bound to {{ getLists.data.data.map(l => ({ label: l.attributes.name, value: l.id })) }}. When the dropdown selection changes, trigger getListProfiles. The resulting Table shows all subscribers in the selected list. Add action buttons for Add to List and Remove from List, each triggering their respective queries and refreshing the list on success via event handlers.

transformer.js
1// JavaScript transformer — format list profiles for display
2const profiles = (data.data || []);
3return profiles.map(profile => {
4 const attrs = profile.attributes || {};
5 return {
6 id: profile.id,
7 email: attrs.email || 'N/A',
8 name: `${attrs.first_name || ''} ${attrs.last_name || ''}`.trim() || 'N/A',
9 subscribed: attrs.subscriptions?.email?.marketing?.consent === 'SUBSCRIBED'
10 ? 'Subscribed'
11 : 'Unsubscribed',
12 added_date: attrs.created
13 ? new Date(attrs.created).toLocaleDateString()
14 : 'N/A'
15 };
16});

Pro tip: When removing profiles from lists, Klaviyo requires the DELETE method with a body — this is unusual for REST APIs. Make sure your Retool query is set to DELETE method and includes the profile ID array in the request body, not as a URL parameter.

Expected result: The list management panel shows all Klaviyo lists in the dropdown. Selecting a list populates the profiles table. The Add and Remove buttons modify list membership and refresh the table on success.

5

Combine Klaviyo data with e-commerce order data

The most powerful Retool-Klaviyo dashboard combines subscriber data from Klaviyo's API with actual order data from your e-commerce database. Add a second resource — your PostgreSQL or MySQL database — to the same Retool app. Create a database query named getCustomerOrders: - SQL: SELECT order_id, created_at, total_amount, status FROM orders WHERE customer_email = '{{ textInput_email.value }}' ORDER BY created_at DESC LIMIT 50 Now the profile lookup panel can show both Klaviyo engagement data (emails received, opened, clicked) and actual purchase data (orders placed, total spend, last purchase date) side by side. This combination is more valuable than either system alone. Create a JavaScript query named combineProfileData that merges both datasets: For RapidDev-style complex integrations that join multiple data sources, Retool's multi-resource app pattern is the ideal architecture. Add a Retool Table showing orders on the left and a Klaviyo event timeline on the right, with a shared email input controlling both datasets. Add a Chart component that plots email engagement events (x-axis) against purchase events (y-axis) over time, revealing the relationship between Klaviyo email touches and conversion. This kind of cross-system analysis is exactly what Retool excels at and is difficult to build in either Klaviyo's dashboard or your e-commerce admin alone.

combine_profile_data.js
1// JavaScript query — merge Klaviyo profile with order data
2// This query runs after both searchProfiles and getCustomerOrders complete
3const klaviyoProfile = searchProfiles.data?.data?.[0];
4const orders = getCustomerOrders.data || [];
5
6if (!klaviyoProfile) return { error: 'Profile not found' };
7
8const attrs = klaviyoProfile.attributes || {};
9const orderStats = {
10 total_orders: orders.length,
11 total_spend: orders.reduce((sum, o) => sum + parseFloat(o.total_amount || 0), 0),
12 last_order_date: orders.length > 0
13 ? new Date(orders[0].created_at).toLocaleDateString()
14 : 'Never',
15 avg_order_value: orders.length > 0
16 ? (orders.reduce((sum, o) => sum + parseFloat(o.total_amount || 0), 0) / orders.length).toFixed(2)
17 : 0
18};
19
20return {
21 klaviyo_id: klaviyoProfile.id,
22 email: attrs.email,
23 name: `${attrs.first_name || ''} ${attrs.last_name || ''}`.trim(),
24 klaviyo_consent: attrs.subscriptions?.email?.marketing?.consent,
25 ...orderStats,
26 total_spend_formatted: `$${orderStats.total_spend.toFixed(2)}`,
27 avg_order_formatted: `$${orderStats.avg_order_value}`
28};

Pro tip: When combining Klaviyo data with order data, run both queries in parallel using Retool's Run on page load setting rather than chaining them sequentially. This halves the total load time for the merged profile view.

Expected result: The combined profile view shows Klaviyo engagement metrics alongside real purchase history. The merged JavaScript query produces a single object with both datasets that can drive summary stat components and charts.

Common use cases

Build a subscriber profile lookup and management panel

Create a Retool app where marketing ops can search for a subscriber by email, view their Klaviyo profile with all properties, see their list memberships, and review their event history (email opens, clicks, purchases). Add buttons to unsubscribe them, add them to a specific list, or update profile properties.

Retool Prompt

Build a subscriber management panel with an email search input, a profile details section showing all Klaviyo properties, a list of the subscriber's list memberships with add/remove buttons, and a timeline of recent events from /profiles/{id}/events filtered by event type.

Copy this prompt to try it in Retool

Campaign performance dashboard with segment comparison

Build a Retool dashboard that lists all recent campaigns with their open rates, click rates, and revenue attributed. Add a segment filter to show only campaigns sent to specific lists, and include a Chart component that visualizes click-through rate trends over the last 90 days.

Retool Prompt

Create a campaign analytics dashboard that fetches campaigns from /campaigns with their metrics, displays open_rate and click_rate in a Table sortable by performance, and shows a bar chart of revenue per campaign using Retool's Chart component.

Copy this prompt to try it in Retool

List health and suppression manager

Build an operational panel that shows all Klaviyo lists with their subscriber counts, growth rates, and suppression percentages. Include tools to view all suppressed addresses, export suppression lists, and bulk-remove invalid addresses that are impacting deliverability scores.

Retool Prompt

Build a list health dashboard that queries all lists from /lists, shows subscriber_count and name for each, and provides a drilldown view showing suppressions for a selected list from /v1/people/exclusions with reason codes and suppression dates.

Copy this prompt to try it in Retool

Troubleshooting

API returns 401 Unauthorized error on all queries

Cause: The private API key is either incorrect, expired, or the resource is missing the required 'revision' header that Klaviyo v2 requires for all requests.

Solution: Verify your private API key in Klaviyo Settings → API Keys. Check that the API key starts with 'pk_' (private key, not a public API key starting with 'pk_'). Add the header 'revision: 2024-02-15' to your Resource's default headers. If using a configuration variable for the key, verify the variable name matches exactly.

Profile search returns empty data array even for an existing email

Cause: Klaviyo's filter syntax for the email search is case-sensitive and requires exact URL encoding. The filter parameter must be formatted exactly as equals(email,'user@example.com') with single quotes around the value.

Solution: Ensure the filter parameter value is properly formatted. The Retool {{ }} expression for the filter URL parameter value should be: equals(email,'{{ textInput_email.value }}'). Verify the email is entered in lowercase. Also confirm the profile exists in the Klaviyo account you're querying — sandbox accounts and production accounts are separate.

typescript
1// URL parameter value for Klaviyo email filter
2// Key: filter
3// Value (use this exact format):
4equals(email,'{{ textInput_email.value.toLowerCase() }}')

List membership query returns 403 Forbidden

Cause: The Klaviyo private API key used for the resource doesn't have the Lists/Segments permission scope enabled. Klaviyo allows granular permission scoping per API key.

Solution: Go to Klaviyo Settings → API Keys, select your private key, and verify that the Lists permission is enabled with at least Read access (and Write access if you need add/remove functionality). Create a new key with the required permissions if needed, then update the configuration variable.

Rate limit errors (429) when loading multiple queries at page load

Cause: Loading too many Klaviyo API queries simultaneously exceeds Klaviyo's rate limit of 75 requests per second per API key. This commonly happens when loading a dashboard with 5+ queries that all trigger on page load.

Solution: Stagger query execution using Retool event handlers instead of loading everything simultaneously. Set only the essential queries (profile lookup, list selector) to run on page load, and trigger detailed queries (event history, metrics) through user interactions. For scheduled batch operations, use Retool Workflows with a Loop block that includes a delay between iterations.

Best practices

  • Store your Klaviyo private API key as a Secret configuration variable in Retool — never paste it directly into query headers or body fields.
  • Always include the 'revision' header in your Klaviyo resource default headers to ensure you're using the stable v2 API and won't be affected by breaking changes in older API versions.
  • Create separate Klaviyo API keys with scoped permissions for your Retool tools — a read-only key for reporting dashboards and a read-write key for management tools.
  • Use cursor-based pagination for list profiles and campaign queries — Klaviyo returns large datasets that must be paginated to avoid timeouts and rate limit issues.
  • Join Klaviyo subscriber data with your e-commerce database orders in the same Retool app to create unified customer profiles that show both engagement and purchase history.
  • Add JavaScript transformers to every Klaviyo query to flatten the nested data.attributes response structure before binding to Table components.
  • Use Retool Workflows on a schedule to pre-cache Klaviyo campaign metrics in a Retool Database table, then query the cached data in your app to avoid rate limit issues on high-traffic dashboards.
  • When building list management tools, add a confirmation modal before any destructive operations (removing subscribers, bulk unsubscribes) to prevent accidental data changes.

Alternatives

Frequently asked questions

Does Klaviyo have a native connector in Retool?

No, Klaviyo does not have a native connector in Retool as of 2026. You need to configure it as a REST API Resource with Bearer token authentication using your Klaviyo private API key. This means you must know the endpoint paths and response structure, but all core operations — profiles, lists, campaigns, and flows — are accessible through the v2 REST API.

What permissions does my Klaviyo API key need for Retool?

Create a private API key in Klaviyo Settings → API Keys with the following permissions: Profiles (Read/Write), Lists (Read/Write), Campaigns (Read), Flows (Read), and Metrics (Read). For read-only dashboards, enable only Read permissions. For subscriber management tools, enable Write permissions on Profiles and Lists. Avoid enabling Data Privacy or Account permissions unless absolutely necessary.

Can I send emails through Klaviyo from Retool?

Yes, you can trigger Klaviyo flow emails from Retool by using the /api/events endpoint to create an event for a profile. Events trigger Klaviyo flows based on your flow conditions. You can also schedule campaign sends using the campaign API. For transactional email sending, Klaviyo's API supports sending to individual profiles via their transactional email endpoint.

How do I handle Klaviyo's cursor-based pagination in Retool?

Klaviyo v2 uses cursor-based pagination with a next cursor in the response's links.next field. To paginate in Retool, store the cursor value in a Variable component and include it as a page[cursor] URL parameter in your query. Build a 'Load More' button that reads the current cursor, passes it to the query, and appends new results to the existing dataset. For full list exports, use a Retool Workflow with a Loop block that continues until links.next is null.

Can I sync Klaviyo suppressions back to my database using Retool?

Yes, you can query Klaviyo's suppressions using the /api/suppression-bulk-create-jobs endpoint and write the results to your database using a second query. Build a Retool Workflow that runs on a schedule (daily or weekly), fetches all new suppressions from Klaviyo since the last sync date, and upserts them into your customer database to keep marketing opt-out records in sync.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Integrations are where projects stall

We wire Retool integrations like this one every week — auth, webhooks, edge cases included. Fixed-price builds from $13K, delivered in 6–10 weeks.

Talk to an integration engineer

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.