Billing
Stripe integration endpoints for subscription management and payment processing
Billing API
The billing API provides Stripe integration for subscription management, payment processing, and webhook handling. All billing operations use Stripe as the payment processor.
Endpoints
Create Checkout Session
Create a Stripe checkout session for subscription purchase.
Endpoint: POST /api/stripe/checkout
Authentication: Required (Bearer token)
Request Headers:
Authorization: Bearer <jwt_token>
Content-Type: application/json
Response (Success):
{
"url": "https://checkout.stripe.com/..."
}
Response (Error - Already Subscribed):
{
"error": "Already subscribed"
}
Status Codes:
200- Checkout session created successfully400- User already has an active subscription401- Authentication failed500- Internal server error
Details:
- Creates a Stripe checkout session in
subscriptionmode - Accepts card payments only
- Redirects to dashboard on success/cancel
- Stores user metadata (userId, email) with the session
- Uses
STRIPE_PRICE_IDenvironment variable for pricing
Example Usage:
const response = await fetch('/api/stripe/checkout', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
});
const data = await response.json();
if (data.url) {
window.location.href = data.url; // Redirect to Stripe checkout
}
Access Billing Portal
Create a Stripe billing portal session for subscription management.
Endpoint: POST /api/stripe/portal
Authentication: Required (Bearer token)
Request Headers:
Authorization: Bearer <jwt_token>
Content-Type: application/json
Response (Success):
{
"url": "https://billing.stripe.com/..."
}
Response (Error - No Subscription):
{
"error": "No active subscription"
}
Status Codes:
200- Portal session created successfully400- User has no active subscription401- Authentication failed500- Internal server error
Details:
- Creates a Stripe billing portal session for existing customers
- Allows users to manage subscriptions, update payment methods, and view invoices
- Requires user to have a valid Stripe customer ID
- Returns to dashboard after portal actions
Example Usage:
const response = await fetch('/api/stripe/portal', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
});
const data = await response.json();
if (data.url) {
window.location.href = data.url; // Redirect to billing portal
}
Stripe Webhooks
Handle Stripe webhook events for subscription lifecycle management.
Endpoint: POST /api/stripe/webhook
Authentication: Stripe signature verification
Request Headers:
stripe-signature: <webhook_signature>
Content-Type: application/json
Response:
{
"received": true
}
Status Codes:
200- Webhook processed successfully400- Invalid signature405- Method not allowed500- Webhook handler failed
Supported Events:
checkout.session.completed
Triggered when a customer completes the checkout process.
Action: Updates user subscription status to ‘active’ and stores:
- Subscription status
- Stripe customer ID
- Stripe subscription ID
- Creation timestamp
customer.subscription.updated
Triggered when a subscription is updated (e.g., plan change, renewal).
Action: Logs subscription update (full implementation pending)
customer.subscription.deleted
Triggered when a subscription is canceled or expires.
Action: Logs subscription cancellation (full implementation pending)
invoice.payment_failed
Triggered when an invoice payment attempt fails.
Action: Logs payment failure (full implementation pending)
Security:
- All webhooks are verified using
STRIPE_WEBHOOK_SECRET - Invalid signatures are rejected with 400 status
- Events are processed idempotently
Example Webhook Payload (checkout.session.completed):
{
"type": "checkout.session.completed",
"data": {
"object": {
"customer": "cus_xxx",
"customer_email": "user@example.com",
"subscription": "sub_xxx",
"metadata": {
"userId": "user_123",
"email": "user@example.com"
}
}
}
}
Pricing Tiers
Subscription pricing is configured in Stripe and referenced via the STRIPE_PRICE_ID environment variable. The checkout session automatically uses this pricing configuration.
Typical Subscription Features:
- Privacy-focused web analytics
- Unlimited tracked sites
- Real-time dashboard access
- Custom event tracking
- Advanced filtering and segmentation
- Share dashboard access
- API access
Configuration
The billing system requires the following environment variables:
STRIPE_SECRET_KEY=sk_live_xxx # Stripe secret API key
STRIPE_PRICE_ID=price_xxx # Stripe price ID for subscription
STRIPE_WEBHOOK_SECRET=whsec_xxx # Webhook signing secret
URL=https://your-domain.com # Application URL for redirects
Error Handling
All billing endpoints return consistent error responses:
{
"error": "Error message description"
}
Common error scenarios:
- 401 Unauthorized - Missing or invalid authentication token
- 400 Bad Request - Invalid request (e.g., already subscribed, no subscription)
- 500 Internal Server Error - Stripe API errors or server issues
CORS Support
All billing endpoints support CORS with:
Access-Control-Allow-Origin: *Access-Control-Allow-Methods: POST, OPTIONSAccess-Control-Allow-Headers: Content-Type, Authorization
OPTIONS preflight requests are handled automatically.
Best Practices
- Always verify authentication before calling billing endpoints
- Handle redirect URLs from checkout and portal sessions
- Monitor webhook events for subscription status changes
- Implement retry logic for failed API calls
- Never expose Stripe secret keys in client-side code
- Use HTTPS for all webhook endpoints in production