Billing

Manage your team's subscription, view available plans, check your SMS credit balance, and access the Stripe billing portal for payment management.

Pricing model

Email is included up to your plan's daily limit. SMS uses a dollar-denominated monthly credit bundle: each send is debited at the destination's zone rate (Zone 1 $0.02 — US/CA, Zone 2 $0.08 — standard markets, Zone 3 $0.25 — premium). When the bundle is exhausted, further sends bill via Stripe Billing Meters at the same per-zone rate. See SMS pricing zones for the full rate card.

List plans

GET
/v1/billing/plans

List all available plans with pricing, daily limits, and SMS bundle. Indicates which plan the team is currently on.

Example Response
{
  "data": [
    {
      "name": "Free",
      "plan": "free",
      "monthlyPrice": 0,
      "dailyEmailLimit": 100,
      "dailySmsLimit": 0,
      "monthlySmsCreditCents": 0,
      "current": true
    },
    {
      "name": "Pro",
      "plan": "pro",
      "monthlyPrice": 29,
      "dailyEmailLimit": 5000,
      "dailySmsLimit": 10000,
      "monthlySmsCreditCents": 200,
      "current": false
    },
    {
      "name": "Scale",
      "plan": "scale",
      "monthlyPrice": 99,
      "dailyEmailLimit": 20000,
      "dailySmsLimit": 100000,
      "monthlySmsCreditCents": 2000,
      "current": false
    },
    {
      "name": "Enterprise",
      "plan": "enterprise",
      "monthlyPrice": 499,
      "dailyEmailLimit": 100000,
      "dailySmsLimit": 500000,
      "monthlySmsCreditCents": 8000,
      "current": false
    }
  ]
}

monthlySmsCreditCentsis the bundle size in cents (AUD). For example, Pro's 200 = $2.00, which covers roughly 25 sends to Australia (Zone 2 at $0.08) or 100 sends to the US (Zone 1 at $0.02).

Get subscription

GET
/v1/billing/subscription

Get the current team's subscription details including plan, status, billing period, and SMS credit balance.

Example Response
{
  "plan": "pro",
  "status": "active",
  "stripeSubscriptionId": "sub_1234567890",
  "currentPeriodStart": "2026-04-21T00:00:00Z",
  "currentPeriodEnd": "2026-05-21T00:00:00Z",
  "cancelAtPeriodEnd": false,
  "smsCreditCentsRemaining": 144,
  "monthlySmsCreditCents": 200
}

smsCreditCentsRemaining resets to monthlySmsCreditCents at the start of each billing period (when Stripe fires invoice.payment_succeeded). Unused credit does not roll over.

Create checkout session

POST
/v1/billing/checkout

Create a Stripe Checkout session to subscribe to a paid plan. Returns a URL to redirect the user to.

Request body

ParameterTypeDescription
planrequiredstringTarget plan: 'pro', 'scale', or 'enterprise'.
cURL
curl -X POST https://api.txtly.com.au/v1/billing/checkout \
  -H "Authorization: Bearer tx_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{"plan": "pro"}'
Response
{
  "url": "https://checkout.stripe.com/c/pay/cs_..."
}

The Checkout session attaches the base plan price plus three metered line items — one per SMS pricing zone. Metered items don't bill at checkout; they accumulate usage over the billing period via Stripe Billing Meters and bill at invoice time.

Create billing portal session

POST
/v1/billing/portal

Create a Stripe Billing Portal session for self-service subscription management (upgrade, downgrade, cancel, payment method updates).

Request body

ParameterTypeDescription
returnUrlstringURL to redirect back to after leaving the portal. Defaults to the dashboard settings page.
Response
{
  "url": "https://billing.stripe.com/p/session/..."
}

Webhook

POST
/v1/webhooks/stripe

Stripe webhook endpoint. Configure this URL in your Stripe Dashboard webhook settings; signature verification is enforced via Stripe-Signature header.

The webhook handles these Stripe events to keep your team's plan + SMS credit in sync:

ParameterTypeDescription
checkout.session.completedeventActivates the subscription, upgrades the plan, anchors the period start, and refills the SMS credit bundle to the plan default.
customer.subscription.updatedeventSyncs plan changes when the subscription is upgraded, downgraded, or set to cancel at period end.
customer.subscription.deletedeventReverts the team to the Free plan and zeroes the SMS credit balance when the subscription is fully cancelled.
invoice.payment_succeededeventRefills the SMS credit bundle to the plan default at the start of each billing period.
invoice.payment_failedeventLogged for monitoring. Stripe retries automatically; on final failure, subscription.deleted fires.

Configuration

Set these environment variables to enable Stripe billing. In production these are sourced from AWS Secrets Manager (txtly/stripe).

ParameterTypeDescription
Stripe__SecretKeyrequiredstringStripe secret API key (sk_live_... or sk_test_...).
Stripe__WebhookSecretrequiredstringWebhook signing secret from Stripe (whsec_...).
Stripe__Prices__ProrequiredstringStripe Price ID for the Pro plan base subscription.
Stripe__Prices__ScalerequiredstringStripe Price ID for the Scale plan base subscription.
Stripe__Prices__EnterpriserequiredstringStripe Price ID for the Enterprise plan base subscription.
Stripe__Prices__SmsZone1OveragerequiredstringStripe metered Price ID linked to the Zone 1 (US/CA) Billing Meter (event_name: sms_zone1_send).
Stripe__Prices__SmsZone2OveragerequiredstringStripe metered Price ID linked to the Zone 2 (Standard) Billing Meter (event_name: sms_zone2_send).
Stripe__Prices__SmsZone3OveragerequiredstringStripe metered Price ID linked to the Zone 3 (Premium) Billing Meter (event_name: sms_zone3_send).
Dashboard__UrlstringDashboard base URL for checkout redirect. Defaults to http://localhost:3000.