These docs are a work in progress and may not be fully up to date. Some pages may contain internal notes for our team.
Skip to Content

API — Billing

Paddle integration endpoints for checkout, customer portal, subscription sync, and invoice access. All authenticated endpoints require auth:api, auth_session, audit. The webhook endpoint is unauthenticated (verified by HMAC-SHA256 signature).

Unauthenticated

POST /webhooks/paddle

Receives Paddle subscription and transaction events. Verifies Paddle-Signature (HMAC-SHA256) and deduplicates via paddle_webhook_events.event_id. See Data model: PaddleWebhookEvent for the full dedup flow and signature detail.

Updates the User’s paddle_subscription_status, subscription_tier, and billing columns on success.

Response 200 on success or duplicate (idempotent).

Authenticated endpoints

POST /billing/checkout

Initiate a Paddle checkout session for a plan upgrade.

Body: { price_id } — Paddle price ID for the target plan.

Response 200: { checkout_url } — redirect the user to this URL.

POST /billing/portal

Generate a Paddle customer portal URL for subscription management.

Response 200: { portal_url }

POST /billing/sync

Force-sync the user’s subscription state from Paddle. Useful after a plan change that the webhook may have missed.

Response 200: Updated user billing fields.

GET /billing/invoices

List the authenticated user’s Paddle transaction/invoice history.

Response 200: Array of invoice objects { id, amount, currency, status, created_at }.

GET /billing/invoices/{transactionId}/pdf

Generate a short-lived PDF URL for a specific invoice.

Params: transactionId — Paddle transaction ID.

Response 200: { url } — short-lived PDF download URL.