Billing API
Read subscription/usage/plan data and create Stripe checkout & billing-portal sessions — api.misar.io/reach/api/billing.
Reach's plan catalog lives in the shared subscription_plans table (product='reach'), independent of any MisarMail subscription — see Cross-Product Contracts. The credits wallet is shared with MisarMail.
Base URL: https://api.misar.io/reach
Get subscription
/api/billing/subscriptionReturns the authenticated user's product='reach' subscription row, joined with plan name/pricing.
curl "https://api.misar.io/reach/api/billing/subscription" \
-H "Authorization: Bearer msr_your_key_here"{
"success": true,
"subscription": {
"planSlug": "pro", "planName": "Pro", "priceMonthly": 79, "priceYearly": null,
"status": "active", "renewalDate": "2026-08-11T00:00:00Z", "cancelAtPeriodEnd": false,
"hasStripeSubscription": true, "hasStripeCustomer": true,
"isTrialing": false, "trialDaysRemaining": null, "trialEndAt": null, "trialPlanSlug": null
}
}Get usage
/api/billing/usageReach's primary metered resource is leads found this billing period (not emails — contrast with MisarMail's equivalent route). Sourced from lead_finder_usage via the get_lead_usage RPC.
leadsLimit is null (unlimited/unset) until per-plan numeric lead caps are configured on the product='reach' subscription_plans rows — today those limits only exist as description text (e.g. "5,000 leads/month"), not a structured column the API can enforce/compare against.
curl "https://api.misar.io/reach/api/billing/usage" \
-H "Authorization: Bearer msr_your_key_here"{ "success": true, "leadsUsed": 1240, "leadsLimit": 5000, "periodStart": "2026-07-01" }List plans
/api/billing/plansReturns the active product='reach' rows from subscription_plans, ordered by sort_order — the same data source the /pricing page and Settings → Billing tab render from.
curl "https://api.misar.io/reach/api/billing/plans"{ "success": true, "plans": [{ "id": "free", "name": "Free", "monthlyPrice": 0, "priceDisplay": "Free", "features": ["1 active channel (email via mail plan)", "50 leads/month", "1 sequence", "Basic CRM pipeline"], "cta": { "label": "Get started", "href": "/signup" } }] }Wallet balance
/api/billing/wallet/balanceReturns the shared Misar wallet credit balance (1 credit = $1). See Wallet — Central API.
{ "success": true, "credits": 42 }Create checkout session
/api/billing/checkoutCreates a Stripe Checkout session to subscribe/upgrade to a paid reach plan.
Body parameters
planSlugstringrequiredOne of "starter" | "pro" | "business".
billingPeriodstring"monthly" (default) or "yearly".
Returns 503 { error: "Plan pricing not configured" } for any plan whose subscription_plans.stripe_price_id is unset. As of this writing, no reach plan has a Stripe price ID configured yet — that's a separate, pending operational task (creating the reach Stripe product catalog), not a bug in this endpoint.
curl -X POST "https://api.misar.io/reach/api/billing/checkout" \
-H "Authorization: Bearer msr_your_key_here" \
-H "Content-Type: application/json" \
-d '{ "planSlug": "pro" }'{ "success": true, "url": "https://checkout.stripe.com/c/pay/..." }Create billing-portal session
/api/billing/portalCreates a Stripe billing-portal session for managing payment method / invoices / cancellation. Auto-creates a Stripe customer on first call if none exists yet.
{ "success": true, "url": "https://billing.stripe.com/session/..." }