Billing API
Check usage, list available tiers, and manage the active plan. Only relevant when DEPLOYMENT_MODE=saas. In self-hosted mode, endpoints still respond but return "saas": false.
Billing status
httpGET /api/billing/status Authorization: Bearer {msp-token} Host: atechsolutions.org # Response (SaaS mode, Growth plan at 41% usage): {{ "saas": true, "tier": "growth", "tier_name": "Growth", "tier_price_cad": 129, "asset_limit": 1000, "total_assets": 412, "usage_pct": 41.2, "usage_status": "ok", # ok | warning | exceeded "trial_days_left": null, "trial_expired": false, "next_tier": {{ "key": "scale", "name": "Scale", "asset_limit": 5000, "price_cad": 349 }}, "billing_email": "[email protected]" }}
http# Response (self-hosted mode): {{ "saas": false, "tier": "selfhosted", "asset_limit": null, "total_assets": 847 }}
usage_status value | Condition | UI behaviour |
|---|---|---|
ok | Under 80% of limit | Green usage bar in sidebar |
warning | 80% or more of limit | Amber usage bar; warning banner on dashboard |
exceeded | At or over 100% of limit | Red usage bar; 402 errors on any asset creation |
List tiers
httpGET /api/billing/tiers Authorization: Bearer {msp-token} # Returns all billable tiers (trial through enterprise): [ {{"key": "trial", "name": "Free Trial", "asset_limit": 250, "price_cad": 0}}, {{"key": "starter", "name": "Starter", "asset_limit": 250, "price_cad": 49}}, {{"key": "growth", "name": "Growth", "asset_limit": 1000, "price_cad": 129}}, {{"key": "scale", "name": "Scale", "asset_limit": 5000, "price_cad": 349}}, {{"key": "enterprise", "name": "Enterprise", "asset_limit": null, "price_cad": null}} ]
Update tier
httpPUT /api/billing/tier Authorization: Bearer {msp-token} Content-Type: application/json {{ "tier": "growth", "billing_email": "[email protected]", "notes": "Stripe customer: cus_abc123" }} # Returns: {{"ok": true, "tier": "growth"}}
This endpoint requires tenants.manage permission. It is intended to be called
by you (the MSP operator) after a customer pays — either manually or via a Stripe webhook.
Tether does not include built-in payment processing.
Stripe webhook integration
To automate tier changes after payment, create a Stripe webhook that calls this endpoint on checkout.session.completed events. Include your MSP admin Bearer token in the webhook handler.
Trial expiry behaviour
New SaaS installations start on a 30-day trial. When the trial expires:
trial_expired: trueis returned in the billing status- Asset creation and CSV import return
402 Payment Required - Existing assets are unaffected — they remain fully accessible
- To lift the block, call
PUT /api/billing/tierwith any paid tier