Stripe Integration
The Billing API is deeply integrated with Stripe for payment processing, subscription management, and billing. All billing operations are handled through Stripe, and webhooks keep the local database synchronized.
Get Stripe Customer Portal URL
Get a secure Stripe Customer Portal URL for billing management. Only account owners can access the customer portal.
Endpoint: https://apis.threatwinds.com/api/billing/v1/stripe/customer
Method: GET
Parameters
Headers
| Header | Type | Required | Description |
|---|---|---|---|
| Authorization | string | Optional* | Bearer token for session authentication |
| api-key | string | Optional* | API key for key-based authentication |
| api-secret | string | Optional* | API secret for key-based authentication |
Note: You must use either Authorization header OR API key/secret combination.
Required Roles
Required role: owner
Only the account owner can access the Stripe Customer Portal.
Request
To get the customer portal URL, use a GET request:
curl -X 'GET' \
'https://apis.threatwinds.com/api/billing/v1/stripe/customer' \
-H 'accept: application/json' \
-H 'Authorization: Bearer <token>'
Or using API key and secret:
curl -X 'GET' \
'https://apis.threatwinds.com/api/billing/v1/stripe/customer' \
-H 'accept: application/json' \
-H 'api-key: your-api-key' \
-H 'api-secret: your-api-secret'
Response
Success Response (200 OK)
{
"url": "https://billing.stripe.com/b/1MdsfD..."
}
Response Schema
| Field | Type | Description |
|---|---|---|
| url | string | Secure Stripe Customer Portal URL |
Customer Portal Features
The Stripe Customer Portal allows customers to:
- View Invoices: Access and download all past invoices
- Update Payment Methods: Add, update, or remove payment methods
- Change Subscription: Upgrade or downgrade subscription tiers
- View Billing History: See complete payment and billing history
- Cancel Subscription: Cancel active subscriptions
Business Logic
- Only owner can access customer portal
- Returns secure Stripe-generated URL
- URL is time-limited and single-use
- Portal session automatically returns to application after actions
Error Codes
| Status Code | Description | Possible Cause |
|---|---|---|
| 200 | OK | Portal URL generated successfully |
| 400 | Bad Request | Invalid request |
| 401 | Unauthorized | Missing or invalid authentication |
| 403 | Forbidden | Not owner (insufficient permissions) |
| 500 | Internal Server Error | Stripe API error |
Stripe Webhook Endpoint
Endpoint: https://apis.threatwinds.com/api/billing/v1/stripe/webhook
Method: POST
IMPORTANT: This endpoint is reserved exclusively for Stripe webhook events and is not intended for direct use by API consumers. The endpoint is secured via Stripe signature verification and processes subscription, invoice, pricing, product, and customer events to keep the billing system synchronized with Stripe.
Do not attempt to call this endpoint directly. All billing operations should be performed through the Stripe Customer Portal or the documented API endpoints.
Stripe Integration Architecture
Data Synchronization
The Billing API maintains eventual consistency with Stripe:
- Customer Creation: Creates customer in Stripe, webhooks sync subscription
- Subscription Changes: Made in Stripe Customer Portal, webhooks sync database
- Tier Management: Tiers created as Stripe prices, webhooks sync features
- Payment Processing: Handled entirely by Stripe, webhooks update status
Example Workflows
Workflow 1: Create Customer and Subscribe
# 1. User creates customer account
curl -X 'POST' \
'https://apis.threatwinds.com/api/billing/v1/customer' \
-H 'Authorization: Bearer <token>' \
-H 'Content-Type: application/json' \
-d '{"email": "john@example.com"}'
# Response: Customer created in Stripe
# 2. Stripe webhook (customer.subscription.created) fires
# - Creates subscription record in database
# - Assigns default tier
# 3. User now has active subscription with default tier
Workflow 2: Change Subscription via Customer Portal
# 1. Owner gets customer portal URL
curl -X 'GET' \
'https://apis.threatwinds.com/api/billing/v1/stripe/customer' \
-H 'Authorization: Bearer <token>'
# Response:
# {
# "url": "https://billing.stripe.com/b/..."
# }
# 2. User opens URL in browser
# 3. User changes subscription tier in Stripe portal
# 4. Stripe webhook (customer.subscription.updated) fires
# 5. Database updates tier and limits automatically
Workflow 3: Handle Failed Payment
1. Stripe attempts to charge customer
↓
2. Payment fails (invoice.payment_failed event)
↓
3. Stripe retries (up to 3 attempts)
↓
4. After 3 failures, invoice.overdue fires
↓
5. Webhook updates subscription status to "past_due"
↓
6. Customer access may be restricted based on status
↓
7. Customer updates payment method in portal
↓
8. Stripe retries and succeeds (invoice.paid event)
↓
9. Webhook updates subscription status to "active"
Best Practices
For Application Developers
- Check Subscription Status: Always check customer subscription status before granting access
- Test with Stripe Test Mode: Use Stripe test mode during development
For Customer Portal
- Direct to Portal: Send owners to Stripe Customer Portal for subscription changes
- Don’t Duplicate UI: Don’t recreate billing UI - use Stripe’s portal
- Handle Returns: Configure return URL in Stripe to bring users back to your app
- Communicate Status: Show subscription status in your application UI
Security Considerations
- Restrict Portal Access: Only allow owners to access customer portal
- Secure API Keys: Never expose Stripe secret keys in frontend code
Troubleshooting
Common Issues
| Issue | Cause | Solution |
|---|---|---|
| Customer portal access denied | User not owner | Only owners can access portal |
| Subscription not reflecting changes | Synchronization delay | Wait a few moments for Stripe to process the change |