Copy-paste ready code examples, detailed API reference, and AI-friendly prompts to get cart recovery running in your Next.js app instantly.
Sign up for free and grab your API key from the dashboard. No credit card required.
Start Free TrialSend cart data when users add items. We'll handle the rest.
await fetch('https://retakeapi.com/api/v1/track', {
method: 'POST',
headers: {
'X-API-Key': process.env.RETAKE_API_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
event: 'CART_UPDATE',
sessionId: user.sessionId,
items: cart.items,
total: cart.total,
currency: 'USD', // optional, defaults to USD
customerEmail: user.email, // optional, see note below
customerName: user.name // optional
})
});When a purchase is made, we automatically cancel pending recovery emails.
await fetch('https://retakeapi.com/api/v1/track', {
method: 'POST',
headers: {
'X-API-Key': process.env.RETAKE_API_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
event: 'ORDER_COMPLETE',
sessionId: user.sessionId,
orderId: order.id, // optional
total: order.total
})
});Act as a Senior Full-Stack Engineer. Your task is to integrate Retake (Cart Recovery System) into a Next.js/React e-commerce application.
Implementation Specs:
1. CART_UPDATE Event:
- Trigger: Whenever the cart state updates (add/remove item, qty change).
- Endpoint: POST https://retakeapi.com/api/v1/track
- Headers:
- 'Content-Type': 'application/json'
- 'X-API-Key': process.env.RETAKE_API_KEY
- Payload:
{
"event": "CART_UPDATE",
"sessionId": "Unique session ID (cookie/localStorage)",
"items": [{ "id": "sku_1", "name": "Product", "price": 100, "quantity": 1 }],
"total": 100.00,
"currency": "USD",
"customerEmail": "[email protected]" // Optional but recommended
}
2. ORDER_COMPLETE Event:
- Trigger: Immediately after successful payment/order placement.
- Endpoint: POST https://retakeapi.com/api/v1/track
- Payload:
{
"event": "ORDER_COMPLETE",
"sessionId": "Same session ID as above",
"orderId": "INV-123",
"total": 100.00
}
3. Important Considerations:
- Debounce the CART_UPDATE calls (e.g., 500ms) to avoid rate limiting during rapid quantity changes.
- Ensure 'sessionId' is consistent across the session.
- 'customerEmail' is optional. If missing, Retake will rely on Webhooks (cart.abandoned) for you to handle email sending.💡 Tip: Paste this into your AI IDE and it will implement cart recovery automatically.
X-API-KeyYour API key from dashboardContent-Typeapplication/json| Parameter | Type | Required | Description |
|---|---|---|---|
event | string | ✓ Yes | Event type: 'CART_UPDATE' or 'ORDER_COMPLETE' |
sessionId | string | ✓ Yes | Unique session/user identifier for cart tracking |
items | array | ✓ Yes | Array of cart items with id, name, price, quantity |
total | number | ✓ Yes | Total cart value in your currency |
currency | string | No | Currency code (default: 'USD') |
customerEmail | string | No | Customer email for direct recovery emails |
customerName | string | No | Customer name for personalized emails |
orderId | string | No | Order ID (for ORDER_COMPLETE event) |
{
"success": true,
"cartId": "cart_abc123",
"scheduledAt": "2024-01-01T01:00:00Z"
}{
"success": true,
"message": "Order completed, recovery emails cancelled"
}If you can't capture the customer's email during cart updates (common in guest checkout flows), you can use webhooks to receive abandoned cart notifications and send recovery emails from your own system.
Configure your webhook URL in the dashboard settings, then handle the cart.abandoned event to look up the customer email from your database and send emails through your preferred service.
// Handle Retake webhooks with signature verification
// app/api/webhooks/retake/route.ts
import { NextRequest, NextResponse } from 'next/server';
import crypto from 'crypto';
// Verify webhook signature
function verifySignature(payload: string, signature: string, secret: string): boolean {
const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(payload).digest('hex');
return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
}
export async function POST(request: NextRequest) {
const body = await request.text();
const signature = request.headers.get('X-Webhook-Signature');
// Verify signature if you configured a webhook secret in dashboard
if (process.env.RETAKE_WEBHOOK_SECRET && signature) {
if (!verifySignature(body, signature, process.env.RETAKE_WEBHOOK_SECRET)) {
return NextResponse.json({ error: 'Invalid signature' }, { status: 401 });
}
}
const payload = JSON.parse(body);
// Payload structure: { event, timestamp, data: { cartId, sessionId, ... } }
switch (payload.event) {
case 'cart.abandoned':
// Fired when no customerEmail provided - send email yourself
const customer = await db.customers.findBySession(payload.data.sessionId);
await sendRecoveryEmail({ to: customer.email, cartItems: payload.data.items });
break;
case 'email.sent':
// Fired after Retake successfully sends recovery email
await analytics.track('recovery_email_sent', payload.data);
break;
case 'cart.recovered':
// Fired when ORDER_COMPLETE received after recovery email was sent
await analytics.track('cart_recovered', { revenue: payload.data.total });
break;
}
return NextResponse.json({ received: true });
}| Event | Description |
|---|---|
cart.abandoned | Fired when a cart is marked as abandoned (after delay period) |
email.sent | Fired when a recovery email is successfully sent |
cart.recovered | Fired when an abandoned cart is converted to an order |
email.clicked | Fired when customer clicks the recovery link in email |
// app/api/cart/update/route.ts
import { NextRequest, NextResponse } from 'next/server';
export async function POST(request: NextRequest) {
const { cart, user } = await request.json();
await fetch('https://retakeapi.com/api/v1/track', {
method: 'POST',
headers: {
'X-API-Key': process.env.RETAKE_API_KEY!,
'Content-Type': 'application/json'
},
body: JSON.stringify({
event: 'CART_UPDATE',
sessionId: user.sessionId,
items: cart.items,
total: cart.total,
customerEmail: user.email
})
});
return NextResponse.json({ success: true });
}Modern email API with great developer experience. Just add your API key.
Amazon Simple Email Service. Great for high-volume sending at low cost.
Reliable email delivery at scale. Just provide your API key.
Powerful email APIs. Configure with your API Key and Domain.
Connect any custom SMTP server. Supports standard auth and TLS.
Get your API key from resend.com.
Create an IAM user with SES permissions. You'll need:
Default region: us-east-1
Create an API Key with "Mail Send" permissions in SendGrid.
Enter your sending domain and private API key from Mailgun.
Enter connection details for your SMTP server.
All email provider credentials are encrypted with AES-256 before storage. We never see your raw API keys, and you can revoke access anytime from the dashboard.
When you track a CART_UPDATE event, Retake schedules recovery emails based on your configured delay (default: 60 minutes). If an ORDER_COMPLETE event is received before the email is sent, we automatically cancel the job—no duplicate emails ever.
No problem! The customerEmail field is optional. Configure webhooks in your dashboard to receive cart.abandoned events, then look up the email from your database and send recovery emails through your own system.
Absolutely. All email provider credentials are encrypted with AES-256 before storage. You own your data, we never see your raw email provider keys, and you can delete everything anytime.
Yes! We provide 4 professionally designed templates included with all plans. You can customize colors, logo, and messaging from the dashboard. Growth and Lifetime plans include full white-label customization.
We automatically append ?session_id=... to your Recovery URL. You should use this parameter to restore the user's cart session when they land on your checkout page.
Join 500+ developers building better e-commerce experiences with Retake. Start for free today.
Start Free Trial