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.

HTTP
POST /v1/billing/checkout

Request

Headers:

Authorization: Bearer hi_live_YOUR_API_KEY
Content-Type: application/json

Body Parameters:

ParameterTypeRequiredDescription
tierStringYesSubscription tier: "pro" or "enterprise"
success_urlStringYesURL to redirect after successful payment
cancel_urlStringYesURL to redirect if user cancels
external_user_idStringNoExternal user ID for B2B2C model

Example Request

Shell
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

JSON
{
  "checkout_url": "https://checkout.stripe.com/c/pay/cs_test_a1...",
  "session_id": "cs_test_a1F386iivKDFGljBNeU4iBmnUGGw7k0dofurJX8JLC1dZAXMo4mSi3n3aP"
}

Next steps:

  1. Redirect user to checkout_url
  2. User completes payment on Stripe-hosted page
  3. Stripe redirects to your success_url
  4. Subscription is automatically activated

Purchase Single Report

Create a one-time payment checkout for a single $29 report analysis.

HTTP
POST /v1/billing/purchase-report

Request

Headers:

Authorization: Bearer hi_live_YOUR_API_KEY
Content-Type: application/json

Body Parameters:

ParameterTypeRequiredDescription
success_urlStringYesURL to redirect after successful payment
cancel_urlStringYesURL to redirect if user cancels
external_user_idStringNoExternal user ID for B2B2C model

Example Request

Shell
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

JSON
{
  "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.

HTTP
GET /v1/subscriptions

Request

Headers:

Authorization: Bearer hi_live_YOUR_API_KEY

Example Request

Shell
curl https://api.homeinsightai.com/v1/subscriptions \
  -H "Authorization: Bearer hi_live_YOUR_API_KEY"

Response

JSON
{
  "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 standing
  • past_due - Payment failed, retrying
  • canceled - Canceled, access ends at current_period_end
  • incomplete - Initial payment pending
  • trialing - In trial period (if applicable)

Customer Portal

Create a Stripe Customer Portal session for managing subscriptions, payment methods, and billing history.

HTTP
POST /v1/billing/portal

Request

Headers:

Authorization: Bearer hi_live_YOUR_API_KEY
Content-Type: application/json

Body Parameters:

ParameterTypeRequiredDescription
return_urlStringYesURL to return to after portal session

Example Request

Shell
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

JSON
{
  "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.

HTTP
GET /v1/billing/tiers

Request

Headers:

Authorization: Bearer hi_live_YOUR_API_KEY

Example Request

Shell
curl https://api.homeinsightai.com/v1/billing/tiers \
  -H "Authorization: Bearer hi_live_YOUR_API_KEY"

Response

JSON
{
  "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).

HTTP
POST /v1/subscriptions

Request

Headers:

Authorization: Bearer hi_live_YOUR_API_KEY
Content-Type: application/json

Body Parameters:

ParameterTypeRequiredDescription
tierStringYesSubscription tier: "pro" or "enterprise"
stripe_customer_idStringYesExisting Stripe Customer ID (must have payment method)
external_user_idStringNoExternal user ID for B2B2C model

Example Request

Shell
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

JSON
{
  "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.

HTTP
DELETE /v1/subscriptions/:subscription_id

Request

Headers:

Authorization: Bearer hi_live_YOUR_API_KEY

Example Request

Shell
curl -X DELETE https://api.homeinsightai.com/v1/subscriptions/sub_1abc123xyz \
  -H "Authorization: Bearer hi_live_YOUR_API_KEY"

Response

JSON
{
  "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.

HTTP
POST /v1/subscriptions/:subscription_id/reactivate

Request

Headers:

Authorization: Bearer hi_live_YOUR_API_KEY

Example Request

Shell
curl -X POST https://api.homeinsightai.com/v1/subscriptions/sub_1abc123xyz/reactivate \
  -H "Authorization: Bearer hi_live_YOUR_API_KEY"

Response

JSON
{
  "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).

HTTP
PUT /v1/subscriptions/:subscription_id/upgrade

Request

Headers:

Authorization: Bearer hi_live_YOUR_API_KEY
Content-Type: application/json

Body Parameters:

ParameterTypeRequiredDescription
new_tierStringYesTarget tier: "pro" or "enterprise"

Example Request

Shell
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

JSON
{
  "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

EventDescription
customer.subscription.createdNew subscription created
customer.subscription.updatedSubscription tier or status changed
customer.subscription.deletedSubscription canceled and ended
invoice.payment_succeededPayment successful
invoice.payment_failedPayment failed (retry or cancel)
checkout.session.completedCheckout session completed successfully

Webhook Signature Verification

Always verify webhook signatures in production:

Python
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:

JavaScript
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:

JavaScript
// 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:

JavaScript
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:

JSON
{
  "error": {
    "code": "no_subscription",
    "message": "No active subscription found. Please subscribe to a plan.",
    "suggested_action": "redirect_to_pricing"
  }
}

Analysis limit exceeded:

JSON
{
  "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:

JSON
{
  "error": {
    "code": "payment_failed",
    "message": "Payment could not be processed. Please update your payment method.",
    "stripe_error": "Your card was declined."
  }
}

Invalid tier:

JSON
{
  "error": {
    "code": "invalid_tier",
    "message": "Invalid tier 'premium'. Valid tiers: pro, enterprise"
  }
}

Credit System API (B2B2C)

The Credit System API enables B2B2C billing where you charge your end-users for document access. Home Insight AI manages the credit accounting while you handle your own pricing and customer relationships.

Get Credit Balance

Get the current credit balance for an external user.

HTTP
GET /v1/credits/balance?external_user_id={user_id}

Headers:

Authorization: Bearer hi_live_YOUR_API_KEY

Query Parameters:

ParameterTypeRequiredDescription
external_user_idStringYesYour user's unique identifier

Response:

JSON
{
  "external_user_id": "user_123",
  "balance": 5,
  "has_unlimited": false,
  "total_purchased": 10,
  "total_spent": 5
}

List Credit Packs

List available credit pack options for purchase.

HTTP
GET /v1/credits/packs

Headers:

Authorization: Bearer hi_live_YOUR_API_KEY

Response:

JSON
[
  {
    "pack_type": "single",
    "name": "Single Analysis",
    "credits": 1,
    "price_cents": 499,
    "price_display": "$4.99",
    "per_credit_display": "$4.99/credit"
  },
  {
    "pack_type": "medium",
    "name": "5 Credits Pack",
    "credits": 5,
    "price_cents": 1999,
    "price_display": "$19.99",
    "per_credit_display": "$3.99/credit"
  },
  {
    "pack_type": "pro",
    "name": "10 Credits Pack",
    "credits": 10,
    "price_cents": 2999,
    "price_display": "$29.99",
    "per_credit_display": "$2.99/credit"
  }
]

Purchase Credits

Create a Stripe checkout session for credit pack purchase.

HTTP
POST /v1/credits/purchase

Headers:

Authorization: Bearer hi_live_YOUR_API_KEY
Content-Type: application/json

Body Parameters:

ParameterTypeRequiredDescription
external_user_idStringYesYour user's unique identifier
pack_typeStringYessingle, medium, or pro
success_urlStringYesURL to redirect after successful payment
cancel_urlStringYesURL to redirect if user cancels
customer_emailStringNoUser's email for Stripe checkout

Example Request:

Shell
curl -X POST https://api.homeinsightai.com/v1/credits/purchase \
  -H "Authorization: Bearer hi_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "external_user_id": "user_123",
    "pack_type": "medium",
    "success_url": "https://yourapp.com/billing/success",
    "cancel_url": "https://yourapp.com/billing/cancel",
    "customer_email": "user@example.com"
  }'

Response:

JSON
{
  "checkout_url": "https://checkout.stripe.com/c/pay/cs_test_a1...",
  "session_id": "cs_test_a1...",
  "external_user_id": "user_123",
  "pack_type": "medium",
  "credits": 5,
  "price_cents": 1999
}

Request Document Access

Request access to documents for an external user (deducts credits).

HTTP
POST /v1/credits/access

Headers:

Authorization: Bearer hi_live_YOUR_API_KEY
Content-Type: application/json
X-External-User-ID: {user_id}

Body Parameters:

ParameterTypeRequiredDescription
external_user_idStringYesYour user's unique identifier
analysis_idsArray[String]YesDocument IDs to access

Credit Logic:

  • Pro/Enterprise users: Free access (0 credits)
  • Already purchased: Free access (cached)
  • New documents: 1 credit per document

Example Request:

Shell
curl -X POST https://api.homeinsightai.com/v1/credits/access \
  -H "Authorization: Bearer hi_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "external_user_id": "user_123",
    "analysis_ids": ["ana_abc123", "ana_def456"]
  }'

Success Response:

JSON
{
  "external_user_id": "user_123",
  "accessible_documents": ["ana_abc123", "ana_def456"],
  "credits_spent": 2,
  "remaining_balance": 3,
  "has_unlimited": false
}

Insufficient Credits Response (HTTP 402):

JSON
{
  "error": "payment_required",
  "message": "Need 2 credits to access 2 documents",
  "credits_required": 2,
  "credits_available": 0,
  "credits_needed": 2,
  "can_unlock": false,
  "purchase_options": [...],
  "subscription_option": {
    "tier": "pro",
    "name": "Pro Subscription",
    "price_display": "$99/month",
    "description": "Unlimited document analyses"
  }
}

Get Purchase History

Get credit purchase history for an external user.

HTTP
GET /v1/credits/history?external_user_id={user_id}&limit=50&offset=0

Headers:

Authorization: Bearer hi_live_YOUR_API_KEY

Query Parameters:

ParameterTypeRequiredDefaultDescription
external_user_idStringYes-Your user's unique identifier
limitIntegerNo50Max results to return
offsetIntegerNo0Pagination offset

Response:

JSON
{
  "external_user_id": "user_123",
  "purchases": [
    {
      "id": "cp_123",
      "pack_type": "medium",
      "credits": 5,
      "price_cents": 1999,
      "status": "completed",
      "created_at": "2024-12-27T10:30:00Z",
      "completed_at": "2024-12-27T10:32:00Z"
    }
  ],
  "total_purchased": 5,
  "total_spent_cents": 1999
}

Credit Pricing

Pack TypeCreditsPricePer Credit
single1$4.99$4.99
medium5$19.99$3.99
pro10$29.99$2.99

Pro/Enterprise Subscription: Unlimited document access for $99/month (Pro) or custom pricing (Enterprise)


Pricing Summary

PlanPriceAnalyses/MonthChat Messages
Free Trial$0150
Pay-Per-Report$29 one-time1 (30 days)Unlimited (30 days)
Pro$99/month100Unlimited
Enterprise$999/monthUnlimitedUnlimited

Next Steps

Billing API - Home Insight AI Documentation