Billing API
The Billing API provides Stripe-powered subscription management and one-time payment processing. All endpoints handle checkout sessions, customer portals, and subscription lifecycle management.
Create Checkout Session
Create a Stripe Checkout session for Pro or Enterprise subscription plans.
POST /v1/billing/checkout
Request
Headers:
Authorization: Bearer hi_live_YOUR_API_KEY
Content-Type: application/json
Body Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
tier | String | Yes | Subscription tier: "pro" or "enterprise" |
success_url | String | Yes | URL to redirect after successful payment |
cancel_url | String | Yes | URL to redirect if user cancels |
external_user_id | String | No | External user ID for B2B2C model |
Example Request
curl -X POST https://api.homeinsightai.com/v1/billing/checkout \
-H "Authorization: Bearer hi_live_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"tier": "pro",
"success_url": "https://yourapp.com/billing/success",
"cancel_url": "https://yourapp.com/billing/cancel"
}'
Response
{
"checkout_url": "https://checkout.stripe.com/c/pay/cs_test_a1...",
"session_id": "cs_test_a1F386iivKDFGljBNeU4iBmnUGGw7k0dofurJX8JLC1dZAXMo4mSi3n3aP"
}
Next steps:
- Redirect user to
checkout_url - User completes payment on Stripe-hosted page
- Stripe redirects to your
success_url - Subscription is automatically activated
Purchase Single Report
Create a one-time payment checkout for a single $29 report analysis.
POST /v1/billing/purchase-report
Request
Headers:
Authorization: Bearer hi_live_YOUR_API_KEY
Content-Type: application/json
Body Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
success_url | String | Yes | URL to redirect after successful payment |
cancel_url | String | Yes | URL to redirect if user cancels |
external_user_id | String | No | External user ID for B2B2C model |
Example Request
curl -X POST https://api.homeinsightai.com/v1/billing/purchase-report \
-H "Authorization: Bearer hi_live_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"success_url": "https://yourapp.com/report/success",
"cancel_url": "https://yourapp.com/pricing"
}'
Response
{
"checkout_url": "https://checkout.stripe.com/c/pay/cs_test_b2...",
"session_id": "cs_test_b2G497jjwLEHImoCPfV5jCnoVHHx8l1epgvsKY9NMD2eAYNPp5nTj4o4bQ"
}
What you get:
- 1 analysis credit added to your account
- Valid for 30 days
- Unlimited chat messages for that analysis
Get Subscription Status
Retrieve current subscription status for the authenticated API key.
GET /v1/subscriptions
Request
Headers:
Authorization: Bearer hi_live_YOUR_API_KEY
Example Request
curl https://api.homeinsightai.com/v1/subscriptions \
-H "Authorization: Bearer hi_live_YOUR_API_KEY"
Response
{
"subscription_id": "sub_1abc123xyz",
"status": "active",
"tier": "pro",
"current_period_start": "2025-11-01T00:00:00Z",
"current_period_end": "2025-12-01T00:00:00Z",
"cancel_at_period_end": false,
"analyses_used": 8,
"analyses_limit": 100,
"created_at": "2025-11-01T00:00:00Z",
"stripe_customer_id": "cus_abc123xyz"
}
Possible statuses:
active- Subscription is active and in good standingpast_due- Payment failed, retryingcanceled- Canceled, access ends atcurrent_period_endincomplete- Initial payment pendingtrialing- In trial period (if applicable)
Customer Portal
Create a Stripe Customer Portal session for managing subscriptions, payment methods, and billing history.
POST /v1/billing/portal
Request
Headers:
Authorization: Bearer hi_live_YOUR_API_KEY
Content-Type: application/json
Body Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
return_url | String | Yes | URL to return to after portal session |
Example Request
curl -X POST https://api.homeinsightai.com/v1/billing/portal \
-H "Authorization: Bearer hi_live_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"return_url": "https://yourapp.com/settings/billing"
}'
Response
{
"portal_url": "https://billing.stripe.com/p/session/test_abc123..."
}
Portal features:
- Update payment method
- View billing history and invoices
- Cancel or reactivate subscription
- Download receipts
- Update billing email
Get Available Tiers
Retrieve all available subscription tiers with pricing information.
GET /v1/billing/tiers
Request
Headers:
Authorization: Bearer hi_live_YOUR_API_KEY
Example Request
curl https://api.homeinsightai.com/v1/billing/tiers \
-H "Authorization: Bearer hi_live_YOUR_API_KEY"
Response
{
"tiers": [
{
"id": "free",
"name": "Free Trial",
"price": 0,
"currency": "USD",
"interval": "month",
"features": [
"1 analysis per month",
"50 chat messages",
"Basic support"
],
"analyses_limit": 1
},
{
"id": "pro",
"name": "Pro",
"price": 99,
"currency": "USD",
"interval": "month",
"features": [
"100 analyses per month",
"Unlimited chat messages",
"Priority support",
"White-label widget",
"Advanced cost estimates"
],
"analyses_limit": 100,
"stripe_price_id": "price_1SZPUkR9pxNkCCCYoc4jXp56"
},
{
"id": "enterprise",
"name": "Enterprise",
"price": 999,
"currency": "USD",
"interval": "month",
"features": [
"Unlimited analyses",
"Unlimited chat messages",
"Dedicated support",
"Custom integrations",
"SLA guarantee",
"On-premise deployment option"
],
"analyses_limit": null,
"stripe_price_id": "price_1SZPVCR9pxNkCCCYbRqZFp52"
}
]
}
Create Subscription (Server-Side)
Create a subscription directly without checkout page (requires Stripe Customer ID).
POST /v1/subscriptions
Request
Headers:
Authorization: Bearer hi_live_YOUR_API_KEY
Content-Type: application/json
Body Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
tier | String | Yes | Subscription tier: "pro" or "enterprise" |
stripe_customer_id | String | Yes | Existing Stripe Customer ID (must have payment method) |
external_user_id | String | No | External user ID for B2B2C model |
Example Request
curl -X POST https://api.homeinsightai.com/v1/subscriptions \
-H "Authorization: Bearer hi_live_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"tier": "pro",
"stripe_customer_id": "cus_abc123xyz"
}'
Response
{
"subscription_id": "sub_1abc123xyz",
"status": "active",
"tier": "pro",
"current_period_start": "2025-11-27T12:00:00Z",
"current_period_end": "2025-12-27T12:00:00Z",
"stripe_subscription_id": "sub_1abc123xyz"
}
Cancel Subscription
Cancel a subscription at the end of the current billing period.
DELETE /v1/subscriptions/:subscription_id
Request
Headers:
Authorization: Bearer hi_live_YOUR_API_KEY
Example Request
curl -X DELETE https://api.homeinsightai.com/v1/subscriptions/sub_1abc123xyz \
-H "Authorization: Bearer hi_live_YOUR_API_KEY"
Response
{
"subscription_id": "sub_1abc123xyz",
"status": "active",
"cancel_at_period_end": true,
"current_period_end": "2025-12-01T00:00:00Z",
"message": "Subscription will be canceled on 2025-12-01T00:00:00Z"
}
Note: Access continues until current_period_end. No refunds for partial months.
Reactivate Subscription
Reactivate a canceled subscription before the end of the current period.
POST /v1/subscriptions/:subscription_id/reactivate
Request
Headers:
Authorization: Bearer hi_live_YOUR_API_KEY
Example Request
curl -X POST https://api.homeinsightai.com/v1/subscriptions/sub_1abc123xyz/reactivate \
-H "Authorization: Bearer hi_live_YOUR_API_KEY"
Response
{
"subscription_id": "sub_1abc123xyz",
"status": "active",
"cancel_at_period_end": false,
"current_period_end": "2025-12-01T00:00:00Z",
"message": "Subscription reactivated successfully"
}
Upgrade/Downgrade Subscription
Change subscription tier (prorated billing applies).
PUT /v1/subscriptions/:subscription_id/upgrade
Request
Headers:
Authorization: Bearer hi_live_YOUR_API_KEY
Content-Type: application/json
Body Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
new_tier | String | Yes | Target tier: "pro" or "enterprise" |
Example Request
curl -X PUT https://api.homeinsightai.com/v1/subscriptions/sub_1abc123xyz/upgrade \
-H "Authorization: Bearer hi_live_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"new_tier": "enterprise"
}'
Response
{
"subscription_id": "sub_1abc123xyz",
"status": "active",
"tier": "enterprise",
"previous_tier": "pro",
"proration_amount": 900,
"proration_currency": "USD",
"current_period_end": "2025-12-01T00:00:00Z",
"message": "Subscription upgraded to enterprise. Prorated amount: $900.00"
}
Proration:
- Upgrade: Immediate charge for prorated difference
- Downgrade: Credit applied to next invoice
Webhook Events
Subscribe to Stripe webhooks to receive real-time billing events:
Endpoint: POST /v1/webhooks/stripe
Supported Events
| Event | Description |
|---|---|
customer.subscription.created | New subscription created |
customer.subscription.updated | Subscription tier or status changed |
customer.subscription.deleted | Subscription canceled and ended |
invoice.payment_succeeded | Payment successful |
invoice.payment_failed | Payment failed (retry or cancel) |
checkout.session.completed | Checkout session completed successfully |
Webhook Signature Verification
Always verify webhook signatures in production:
import stripe
# Your webhook secret from Stripe Dashboard
webhook_secret = "whsec_..."
# Verify signature
stripe.Webhook.construct_event(
payload=request.body,
sig_header=request.headers["Stripe-Signature"],
secret=webhook_secret
)
See Webhooks documentation for full implementation guide.
Best Practices
1. Handle Checkout Redirects
After creating a checkout session, immediately redirect the user:
const response = await fetch('/v1/billing/checkout', {
method: 'POST',
headers: {
'Authorization': 'Bearer hi_live_YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
tier: 'pro',
success_url: window.location.origin + '/billing/success',
cancel_url: window.location.origin + '/pricing'
})
})
const { checkout_url } = await response.json()
window.location.href = checkout_url // Redirect immediately
2. Check Subscription Status Before API Calls
Cache subscription status to avoid rate limits:
// Cache for 5 minutes
const cachedStatus = localStorage.getItem('subscription_status')
const cacheTime = localStorage.getItem('subscription_cache_time')
if (!cachedStatus || Date.now() - cacheTime > 300000) {
const response = await fetch('/v1/subscriptions', {
headers: { 'Authorization': 'Bearer hi_live_YOUR_API_KEY' }
})
const status = await response.json()
localStorage.setItem('subscription_status', JSON.stringify(status))
localStorage.setItem('subscription_cache_time', Date.now())
}
3. Handle Failed Payments
Display clear messaging for past_due status:
if (subscription.status === 'past_due') {
showAlert('Your payment failed. Please update your payment method.')
redirectToPortal()
}
4. Test with Stripe Test Mode
Use Stripe test cards for development:
Successful payment: 4242 4242 4242 4242
Failed payment: 4000 0000 0000 0002
Requires 3DS: 4000 0025 0000 3155
Error Handling
Common Errors
No active subscription:
{
"error": {
"code": "no_subscription",
"message": "No active subscription found. Please subscribe to a plan.",
"suggested_action": "redirect_to_pricing"
}
}
Analysis limit exceeded:
{
"error": {
"code": "limit_exceeded",
"message": "Monthly analysis limit reached (100/100). Upgrade to Enterprise for unlimited analyses.",
"analyses_used": 100,
"analyses_limit": 100,
"suggested_action": "upgrade_tier"
}
}
Payment failed:
{
"error": {
"code": "payment_failed",
"message": "Payment could not be processed. Please update your payment method.",
"stripe_error": "Your card was declined."
}
}
Invalid tier:
{
"error": {
"code": "invalid_tier",
"message": "Invalid tier 'premium'. Valid tiers: pro, enterprise"
}
}
Pricing Summary
| Plan | Price | Analyses/Month | Chat Messages |
|---|---|---|---|
| Free Trial | $0 | 1 | 50 |
| Pay-Per-Report | $29 one-time | 1 (30 days) | Unlimited (30 days) |
| Pro | $99/month | 100 | Unlimited |
| Enterprise | $999/month | Unlimited | Unlimited |
Next Steps
- Webhooks API - Handle billing events
- B2B2C Model - White-label billing for your customers
- React SDK - Embed payment UI components