Billing
Five read-only endpoints for inspecting the current team's billing state. Useful for in-app dashboards, programmatic plan checks, and accounting integrations.
All write actions (changing plan, updating payment method, cancelling) live in the dashboard only - they cannot be performed via the API.
Base URL: https://formspring.io/api/v1
| Method | Path | Ability |
|---|---|---|
| GET | /billing/team |
billing:read |
| GET | /billing/plan |
billing:read |
| GET | /billing/usage |
billing:read |
| GET | /billing/subscription |
billing:read |
| GET | /billing/invoices |
billing:read |
Every endpoint requires a token minted with the billing:read ability. See Tokens & abilities → and Roles →.
All prices and invoice amounts are in USD.
Show team
GET /billing/team
Returns the current team's identity and billing-relevant metadata.
Response 200:
{
"data": {
"id": 42,
"name": "Acme Co.",
"owner_id": 7,
"personal_team": false,
"members_count": 4,
"created_at": "2025-08-01T00:00:00+00:00"
}
}
Show plan
GET /billing/plan
Returns the plan the team is on, including price, feature flags, and included quotas.
Response 200:
{
"data": {
"key": "team",
"name": "Team",
"price": 49,
"is_free": false,
"features": {
"webhooks": true,
"api_access": true,
"mcp_server": true,
"team_rbac": true,
"ai_features": true,
"agency": true,
"surveys": true,
"funnels": true,
"links": true,
"links_custom_slug": true,
"links_branded_domain": true
},
"limits": {
"monthly_submissions": 25000,
"forms": null,
"storage_gb": 50,
"retention_days": null,
"team_members": 10,
"links_max": 10000,
"links_analytics_retention_days": 365,
"links_branded_domains_max": 1
}
}
}
key is one of free, pro, team, scale. price is the monthly price in USD (0, 19, 49, 149). null limits mean unlimited.
Show usage
GET /billing/usage
Current billing period's usage snapshot. Refreshes within 60 seconds of new submissions arriving.
Each metered entry has the shape { value, limit, percent, state, resets_at }, where state is ok (under 80 % of the limit), warning (80-100 %), or critical (at or over the limit). Unlimited meters (limit: null) always report ok.
Response 200:
{
"data": {
"period": "2026-06",
"resets_at": "2026-06-30T23:59:59+00:00",
"submissions": {
"value": 12384,
"limit": 25000,
"percent": 49.5,
"state": "ok",
"resets_at": "2026-06-30T23:59:59+00:00"
},
"storage": {
"value": 1.25,
"limit": 50,
"percent": 2.5,
"state": "ok",
"resets_at": "2026-06-30T23:59:59+00:00"
},
"webhooks": {
"value": 310,
"limit": null,
"percent": 0,
"state": "ok",
"resets_at": "2026-06-30T23:59:59+00:00"
}
}
}
storage.value is in gigabytes. Plan a UI by reading value / limit - or just render the precomputed percent and color by state.
Show subscription
GET /billing/subscription
The active subscription's lifecycle state.
Response 200:
{
"data": {
"state": "active",
"on_trial": false,
"on_grace_period": false,
"past_due": false,
"canceled": false,
"ends_at": null,
"trial_ends_at": null,
"stripe_status": "active"
}
}
state is one of: none, on_trial, active, past_due, on_grace_period, canceled. Free-plan teams (no subscription) get state: "none" with the boolean flags false and the timestamps null. A team in past_due can still receive submissions but cannot create new resources. A canceled subscription that is still inside its paid period reports on_grace_period, with ends_at set to when access lapses.
List invoices
GET /billing/invoices
All invoices in reverse chronological order. Not paginated. Teams with no billing history (including Free teams) get an empty data array.
Response 200:
{
"data": [
{
"id": "in_1PXh2K...",
"number": "ACME-2026-0007",
"total": 4900,
"status": "paid",
"date": "2026-05-01T00:00:12+00:00",
"hosted_invoice_url": "https://invoice.stripe.com/i/acct_.../..."
}
]
}
total is in USD cents (4900 = $49.00). hosted_invoice_url opens the payment processor's hosted invoice page, with a PDF download available there.
Common errors
| Status | Meaning |
|---|---|
401 |
Token missing or invalid |
402 |
Team's plan doesn't include API access |
403 |
Token lacks the billing:read ability |
429 |
API rate limit hit |