Overview
Loops provides a simple API to create checkout sessions for accepting payments. This guide will walk you through the essential steps to get started.
1. Get Your API Key
To use the Loops API, you’ll need an API key for authentication.
Where to Find Your API Key
- Log in to your Loops Dashboard
- Navigate to Settings → API Keys
- Click Create API Key or copy your existing key
- Store your API key securely (treat it like a password!)
Keep your API key secure! Never expose it in client-side code or public repositories. Always use environment variables or secure secret management.
Using Your API Key
Include your API key in the Authorization
header of all API requests:
Authorization: Bearer your_api_key_here
2. Create a Checkout Session
A checkout session is a secure, temporary link where your customers can complete their payment.
Basic Example (V2 API - Recommended)
import { Loops } from "@loops-fi/sdk";
const loops = new Loops({
apiKey: process.env.LOOPS_API_KEY,
});
async function createCheckout() {
const session = await loops.checkoutSessions.create({
paymentLinkId: "pl_1234567890",
externalCustomerId: "customer_123",
metadata: {
orderId: "order_456",
source: "website",
},
});
console.log("Checkout URL:", session.url);
// Redirect your customer to session.url
}
Request Parameters
Parameter | Type | Required | Description |
---|
paymentLinkId | string | Yes | The ID of your payment link (create one in your dashboard) |
externalCustomerId | string | No | Your internal customer identifier |
metadata | object | No | Custom data to attach to the session (max 50 keys) |
Response
The API returns a checkout session object:
{
"id": "cs_abc123",
"url": "https://checkout.loops.fi/cs_abc123",
"paymentLinkId": "pl_1234567890",
"externalCustomerId": "customer_123",
"status": "open",
"metadata": {
"orderId": "order_456",
"source": "website"
},
"createdAt": "2025-01-15T10:30:00Z"
}
Next step: Redirect your customer to the url
field to complete their payment.
3. Handle Webhooks
Webhooks notify your application when events occur, such as successful payments or failed transactions.
Setting Up Webhooks
- Go to your Loops Dashboard
- Navigate to Settings → Webhooks
- Click Add Endpoint
- Enter your webhook URL (e.g.,
https://yourdomain.com/api/webhooks/loops
)
- Select which events you want to receive
- Save and copy your webhook signing secret
Webhook Events
Loops sends webhooks for the following events:
checkout.session.completed
- Payment was successful
checkout.session.expired
- Session expired without payment
checkout.session.failed
- Payment failed
Receiving Webhooks
Create an endpoint in your application to receive webhook events:
// app/api/webhooks/loops/route.ts
import { headers } from 'next/headers';
import { NextResponse } from 'next/server';
export async function POST(req: Request) {
const body = await req.text();
const headersList = await headers();
const signature = headersList.get('loops-signature');
// Verify the webhook signature (recommended)
// Use your webhook signing secret from the dashboard
const event = JSON.parse(body);
switch (event.type) {
case 'checkout.session.completed':
// Payment successful - fulfill the order
const session = event.data;
console.log('Payment successful:', session.id);
// TODO: Update your database, send confirmation email, etc.
break;
case 'checkout.session.failed':
// Payment failed
console.log('Payment failed:', event.data.id);
break;
case 'checkout.session.expired':
// Session expired
console.log('Session expired:', event.data.id);
break;
}
return NextResponse.json({ received: true });
}
Webhook Event Structure
All webhook events follow this structure:
{
"id": "evt_abc123",
"type": "checkout.session.completed",
"created": "2025-01-15T10:35:00Z",
"data": {
"id": "cs_abc123",
"url": "https://checkout.loops.fi/cs_abc123",
"status": "completed",
"paymentLinkId": "pl_1234567890",
"externalCustomerId": "customer_123",
"metadata": {
"orderId": "order_456",
"source": "website"
},
"createdAt": "2025-01-15T10:30:00Z",
"completedAt": "2025-01-15T10:35:00Z"
}
}
Verifying Webhook Signatures
Always verify webhook signatures in production to ensure the request is genuinely from Loops and hasn’t been tampered with.
import crypto from 'crypto';
function verifyWebhookSignature(
payload: string,
signature: string,
secret: string
): boolean {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
}
// Usage in your webhook handler
const isValid = verifyWebhookSignature(
req.body, // raw body string
req.headers['loops-signature'],
process.env.LOOPS_WEBHOOK_SECRET
);
if (!isValid) {
return res.status(401).json({ error: 'Invalid signature' });
}
Testing Webhooks Locally
Use a tool like ngrok to expose your local server:
# Start ngrok
ngrok http 3000
# Use the ngrok URL as your webhook endpoint
# Example: https://abc123.ngrok.io/api/webhooks/loops
Next Steps
Need Help?