Klaviyo IntegrationPRODUCTION READY
Complete setup guide for OAuth 2.0 integration with Klaviyo API
Overview
This documentation provides complete instructions for setting up and configuring the Klaviyo OAuth integration for your Clivo Email application. The integration uses OAuth 2.0 with PKCE (Proof Key for Code Exchange) for enhanced security.
Integration Status
- Backend OAuth endpoints configured
- Frontend connection handler implemented
- Security middleware enabled
- PKCE flow implemented
- Token refresh mechanism active
Klaviyo Dashboard Configuration
Configure these settings in your Klaviyo Developer Portal to enable OAuth integration.
Required Settings
| Setting | Production Value | Development Value |
|---|---|---|
| OAuth Installation URL | https://app.clivo.email/settings | http://localhost:3000/settings |
| Redirect URI | https://api.clivo.email/klaviyo/oauthcallback | http://localhost:5000/klaviyo/oauthcallback |
| Client ID | 31527874-9279-4822-b253-a78223928a21 | |
| Client Secret | (Stored in .env file) | |
Important: OAuth Installation URL
The OAuth Installation URL is where users START the integration process. This is your Settings page where the "Connect Klaviyo" button is located.
For Klaviyo Dashboard, enter:
Required Scopes
Configure these scopes in your Klaviyo application to enable all necessary permissions:
- accounts:read - Read account information
- profiles:read - Access customer profiles
- campaigns:read - Read email campaigns
- campaigns:write - Create and update campaigns
- templates:read - Access email templates
- templates:write - Create and update templates
- lists:read - Read customer lists
OAuth Integration Flow
Complete step-by-step flow of the OAuth 2.0 PKCE authentication process:
URL: https://app.clivo.email/settings
Trigger: handleOAuthConnect function (Settings.js:230)
API Call: GET /api/oauth/connect/klaviyo
Generates PKCE code challenge, creates state parameter with user info, returns Klaviyo auth URL
URL: https://www.klaviyo.com/oauth/authorize?...
User authenticates and grants permissions
URL: https://api.clivo.email/klaviyo/oauthcallback?code=...
Validates code and state, exchanges authorization code for access/refresh tokens, fetches Klaviyo account info
Stores: access_token, refresh_token, account_id, account_name
URL: https://app.clivo.email/settings?connected=klaviyo
Backend API Endpoints
1. Initiate OAuth Flow
GET /api/oauth/connect/klaviyo
Query Parameters:
accountName: Name for this connection
Response:
{
"authUrl": "https://www.klaviyo.com/oauth/authorize?..."
}
2. OAuth Callback Handler
GET /klaviyo/oauthcallback
Query Parameters:
code: Authorization code from Klaviyo
state: State parameter (contains user info)
Success: Redirects to /settings?connected=klaviyo
Error: Redirects to /settings?error=klaviyo_connection_failed
3. Get Connected Accounts
GET /api/oauth/accounts
Headers:
Authorization: Bearer {token}
Response:
{
"success": true,
"accounts": [
{
"id": "...",
"platform": "klaviyo",
"accountName": "Primary Marketing",
"connectedAt": "2025-11-27T10:30:00Z"
}
]
}
4. Disconnect Account
DELETE /api/oauth/accounts/:accountId
Headers:
Authorization: Bearer {token}
Response:
{
"success": true,
"message": "Account disconnected successfully"
}
Frontend Implementation
Settings.js - handleOAuthConnect
This function initiates the OAuth flow from the frontend:
const handleOAuthConnect = async (platform) => {
try {
const accountName = prompt('Enter account name:');
if (!accountName) return;
// Call backend to get OAuth URL
const response = await api.get(
`/oauth/connect/${platform}?accountName=${encodeURIComponent(accountName)}`
);
// Redirect to Klaviyo authorization
window.location.href = response.data.authUrl;
} catch (error) {
console.error('OAuth initiation error:', error);
enqueueSnackbar('Failed to connect', { variant: 'error' });
}
};
Usage Example
<button onClick={() => handleOAuthConnect('klaviyo')}>
Connect Klaviyo Account
</button>
Environment Variables
Configure these variables in your .env file:
# Klaviyo OAuth Configuration
KLAVIYO_CLIENT_ID=31527874-9279-4822-b253-a78223928a21
KLAVIYO_CLIENT_SECRET=QqcpV8D3XRPHw_fr5mTRsEQ0CmcrtKbNz83oegUvSAaNB36PL0H0sEhHeTuoVZVUIjZWLmgdaHfRiKrDcEp96A
KLAVIYO_REDIRECT_URI=http://localhost:5000/klaviyo/oauthcallback
# For Production, change to:
# KLAVIYO_REDIRECT_URI=https://api.clivo.email/klaviyo/oauthcallback
Security Warning
Never commit the .env file to version control. Keep your Client Secret confidential and rotate it regularly.
Security Features Implemented
1. PKCE Flow for OAuth
Uses Proof Key for Code Exchange (PKCE) for enhanced security:
- Code verifier generated on backend
- Code challenge sent to Klaviyo
- Code verifier used during token exchange
- Prevents authorization code interception attacks
2. Security Middleware
- Helmet.js security headers (CSP, HSTS, XSS protection)
- CORS with whitelisted origins
- Input sanitization and validation
- Security event logging
- Rate limiting on API endpoints
3. Token Management
Secure token storage and refresh mechanisms:
- Encrypted token storage in database
- Automatic token refresh before expiry
- Secure token transmission over HTTPS
- Token revocation on disconnect
JWT Bearer Token Authentication
All protected API endpoints require JWT authentication.
Manual Token Usage
fetch('https://api.clivo.email/api/oauth/accounts', {
headers: {
'Authorization': 'Bearer YOUR_JWT_TOKEN'
}
})
Automatic Token Injection (Recommended)
The API helper automatically adds tokens to all requests:
import { api } from '../utils/api';
// Token is automatically added!
api.get('/oauth/accounts');
Testing Checklist
Backend Tests
- API server running on port 5000
- MongoDB connected successfully
- OAuth endpoints accessible
- Environment variables loaded correctly
- PKCE implementation working
Frontend Tests
- Settings page loads correctly
- "Connect Klaviyo" button visible
- Click triggers OAuth flow
- Redirects to Klaviyo authorization page
- Success/error messages display properly
Integration Tests
- Complete OAuth flow from start to finish
- Account saved to database correctly
- Tokens stored and encrypted
- User redirected back with success message
- Connected account appears in account list
- Disconnect functionality works
Troubleshooting
Issue: "OAuth installation URL" confusion
Solution
The OAuth installation URL is where users START the process (your Settings page), NOT the callback URL.
Enter in Klaviyo: https://app.clivo.email/settings
Issue: "redirect_uri_mismatch" error
Solution
Ensure the Redirect URI in Klaviyo dashboard EXACTLY matches KLAVIYO_REDIRECT_URI in your .env file. Check for trailing slashes and protocol (http vs https).
Issue: 401 Unauthorized errors
Solution
Ensure you're using the API helper that automatically adds Bearer tokens:
import { api } from '../utils/api';Issue: Token expired errors
Solution
The system should automatically refresh tokens. If this fails, ask the user to reconnect their Klaviyo account from Settings > Integrations.
Key Files Reference
| File | Purpose | Location |
|---|---|---|
| oauthRoutes.js | OAuth connection endpoints | /api/routes/oauthRoutes.js |
| server.js | Klaviyo callback handler | /api/server.js (Line 187-339) |
| Settings.js | Frontend connection UI | /app/src/apps/ai-email/pages/Settings.js |
| api.js | API helper with auto-token | /app/src/utils/api.js |
| security.js | Security middleware | /api/middleware/security.js |
| auth.js | JWT authentication | /api/middleware/auth.js |
Quick Reference
Start Development Servers
# Backend
cd api
pm2 start server.js --name api
# Frontend
cd app
npm start
View Logs
pm2 logs api
Test OAuth Flow
1. Visit: http://localhost:3000/settings
2. Click "Connect Klaviyo Account"
3. Enter account name
4. Approve in Klaviyo
5. Verify redirect back to Settings
6. Check database for saved account