Configuration
The settings for revenue tracking, for the Stripe webhook, the HTTP API and the @supapulse/revenue SDK.
Stripe webhook
| Setting | Value |
|---|---|
| URL | https://supapulse.app/api/webhooks/stripe/{publicToken}, shown with your token in the site's settings |
| Events | checkout.session.completed, invoice.paid, charge.refunded, customer.subscription.updated, customer.subscription.deleted |
| Signing secret | The whsec_… secret Stripe shows for the endpoint, saved in the site's settings |
| Signature tolerance | 5 minutes |
| Success | 200 with { "received": true } |
See the Stripe guide.
HTTP API
| Setting | Value |
|---|---|
| URL | https://supapulse.app/api/ingest |
| Method | POST |
| Headers | Content-Type: application/json, X-API-Token: sec_… |
| Body | { "type": "revenue", "data": { … } } |
| Success | 202 Accepted with { "success": true } |
| Rate limit | 2,000 requests per hour per IP address |
The token can also go in the body as "token": "sec_…" instead of the header. The header wins if both are set.
Visitor fingerprint endpoint
| Setting | Value |
|---|---|
| URL | https://supapulse.app/api/fingerprint |
| Method | POST |
| Auth | The site's token, in X-API-Token or a token body field. Call it from the browser with the public token. |
| Success | 200 with { "visitor_fingerprint": "…" } |
getVisitorFingerprint() in @supapulse/core calls it for you and caches the result. The endpoint shares the ingest rate limit.
@supapulse/revenue options
const revenue = new Revenue({
apiToken: process.env.SUPAPULSE_SECRET_TOKEN!, // required
endpoint: 'https://supapulse.app/api/ingest',
debug: false,
maxRetries: 3,
retryBackoff: 1000,
});| Option | Type | Default | What it does |
|---|---|---|---|
apiToken | string | none | The secret token. The constructor throws without it. |
endpoint | string | https://supapulse.app/api/ingest | Where events are sent. |
debug | boolean | false | Logs sends and retries with a [Supapulse Revenue] prefix. |
maxRetries | number | 3 | Attempts per event for network errors and 429. |
retryBackoff | number | 1000 | Base delay in milliseconds; doubles after each failed attempt. A 429 waits for Retry-After instead. |
Any other 4xx (401, 402, 403, 422) isn't retried: track() throws on the first one.
Environment variables
| Variable | Where | Value |
|---|---|---|
SUPAPULSE_SECRET_TOKEN | Server only | sec_… |
NEXT_PUBLIC_SUPAPULSE_TOKEN (or your framework's public prefix) | Browser | pub_… |
Use one Supapulse site per environment if you want test payments kept out of production numbers.
Serverless and edge runtimes
The HTTP API is one fetch call, so it runs anywhere fetch does: Node.js, Vercel and Netlify functions, AWS Lambda, Cloudflare Workers, Deno and Bun. Await the call before the function returns, or the runtime may freeze it mid-request.
Security checklist
- The secret token lives only in server environment variables and your secrets manager.
- Webhook signatures are verified before any revenue is sent.
- Revenue is sent only for payments that succeeded, and refunds are sent as refunds.
- The secret token is regenerated after anyone with access leaves, or after a leak.
Basic usage
Send purchases, subscription payments, refunds and cancellations to Supapulse from your server, keyed by customer ID.
API reference
The revenue and identify events the ingest API accepts, the fingerprint endpoint, the Stripe webhook, what each stores, and the @supapulse/revenue SDK surface.