Skip to main content

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

  1. Log in to your Loops Dashboard
  2. Navigate to SettingsAPI Keys
  3. Click Create API Key or copy your existing key
  4. 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.
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

ParameterTypeRequiredDescription
paymentLinkIdstringYesThe ID of your payment link (create one in your dashboard)
externalCustomerIdstringNoYour internal customer identifier
metadataobjectNoCustom 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

  1. Go to your Loops Dashboard
  2. Navigate to SettingsWebhooks
  3. Click Add Endpoint
  4. Enter your webhook URL (e.g., https://yourdomain.com/api/webhooks/loops)
  5. Select which events you want to receive
  6. 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?

I