Codapult
PreisePluginsDoku
Codapult

Das SaaS-Boilerplate für Macher

Produkt

  • Preise
  • Plugins
  • Dokumentation

Unternehmen

  • Kontakt
  • GitHub

Rechtliches

  • Datenschutzrichtlinie
  • Nutzungsbedingungen

© 2026 Codapult. Alle Rechte vorbehalten.

Alle Artikel

Getting Started

  • Introduction
  • Quick Start
  • Project Structure

Configuration

  • Environment Variables
  • App Configuration

Authentication

  • Authentication
  • OAuth Providers
  • Two-Factor & Passwordless
  • Enterprise SSO (SAML)

Database

  • Database
  • Migrations

Teams

  • Teams & Organizations
  • Permissions & RBAC

Payments

  • Payments & Billing
  • Stripe Setup
  • LemonSqueezy Setup
  • Polar Setup
  • Payment Webhooks

Api

  • API Layer
  • tRPC
  • GraphQL

Ai

  • AI Features

Email

  • Email
  • Email Templates

Infrastructure

  • Infrastructure
  • File Storage
  • Background Jobs

Ui

  • UI & Theming

I18n

  • Internationalization

Content Management

  • Content Management

Admin

  • Admin Panel

Security

  • Security

Monitoring

  • Analytics & Monitoring

Modules

  • Module Architecture

Plugins

  • Plugin System
  • AI Kit Plugin
  • CRM Plugin
  • Helpdesk Plugin
  • Email Marketing Plugin

Deployment

  • Deployment
  • Troubleshooting

Upgrading

  • Upgrading Codapult

Developer Tools

  • MCP Server
  • Testing
Payments

Payment Webhooks

How Codapult handles payment webhooks, extending handlers, and testing locally.

Payment providers notify your app of subscription events via webhooks. Both Stripe and LemonSqueezy webhooks are handled through the same normalized interface.

Endpoints

ProviderEndpoint
StripePOST /api/webhooks/stripe
LemonSqueezyPOST /api/webhooks/lemonsqueezy

Signature Verification

Every incoming webhook is verified against its signing secret before processing. Invalid signatures are rejected with a 400 status. Set the corresponding secret:

  • Stripe: STRIPE_WEBHOOK_SECRET
  • LemonSqueezy: LEMONSQUEEZY_WEBHOOK_SECRET

Handled Events

EventAction
checkout.session.completedActivate subscription, link to user
customer.subscription.createdRecord new subscription
customer.subscription.updatedUpdate plan, seats, or status
customer.subscription.deletedCancel and deactivate subscription

Webhook payloads include metadata (userId, planId) set during checkout creation.

Delivery Logging

All webhook deliveries are logged in the webhook_delivery table with the event type, status, and payload. View delivery history in Admin → Webhooks.

Failed deliveries are retried via the webhook-retry background job with exponential backoff.

Extending the Handler

To add custom logic when a payment event occurs, edit the webhook handler in the corresponding route file:

// src/app/api/webhooks/stripe/route.ts
case 'checkout.session.completed':
  await activateSubscription(session);
  // Add your custom logic here:
  // await sendWelcomeEmail(session.customer_email);
  // await provisionResources(session.metadata.planId);
  break;

Testing Locally

Stripe CLI

stripe listen --forward-to http://localhost:3000/api/webhooks/stripe

Trigger test events:

stripe trigger checkout.session.completed
stripe trigger customer.subscription.updated

LemonSqueezy

Use ngrok or a similar tunnel to expose your local server:

ngrok http 3000

Then set the ngrok URL as the webhook endpoint in the LemonSqueezy dashboard.

Polar SetupAPI Layer