Minimal server-side billing/provisioning service for LaunchGuard.
- Receives Paddle subscription webhooks.
- Verifies every webhook signature using Paddle's official Node.js SDK.
- Stores a lean subscription/entitlement cache in Postgres.
- Uses idempotent/out-of-order-safe subscription upserts.
- Keeps Paddle API keys and webhook secrets off the Chrome extension.
- Run
npm install. - Create/connect a Neon Postgres database in Vercel.
- Run
db/schema.sqlin the Neon SQL editor. - Set server-only environment variables:
DATABASE_URLPADDLE_API_KEY(sandbox key while testing)PADDLE_ENV=sandbox
- Deploy to Vercel.
- Confirm
/api/healthreturns{ "ok": true, ... }. - In Paddle Sandbox: Developer tools -> Notifications -> New destination.
- URL:
https://YOUR-PROJECT.vercel.app/api/paddle/webhook - Events:
subscription.created,subscription.updated
- URL:
- Save the destination, copy its Secret key, add it to Vercel as
PADDLE_WEBHOOK_SECRET, then redeploy. - Use Paddle Notifications -> Simulations to send
subscription.createdandsubscription.updatedevents. - Confirm both return HTTP 200, then run:
SELECT subscription_id, customer_id, status, entitled, price_id, product_id, event_occurred_at
FROM paddle_subscriptions
ORDER BY event_occurred_at DESC;Never expose PADDLE_API_KEY, PADDLE_WEBHOOK_SECRET, or DATABASE_URL in the extension or frontend. The webhook handler verifies Paddle's signature before changing entitlement state.
The installation_id field is ready for the next step, where the external checkout page will pass a random LaunchGuard installation ID through Paddle customData, allowing automatic Pro unlock for the correct extension installation.