Skip to content

Billing

Flatstack has three plans, each a flat monthly price in GBP, VAT exclusive. Usage never adds a charge: going over a limit slows things down or blocks them instead.

Signing up

There are no free accounts and no trials. After you create a login, choose a plan and pay through Stripe Checkout. Your account exists once Stripe confirms the payment. Until then the login can only see the plan picker and checkout.

Request What it does
GET /v1/billing/plans Lists the plans, prices in pence and limits.
POST /v1/billing/checkout { "planId" }. Returns { "url" } for Stripe Checkout.

Changing plan

Only account owners can change billing.

Request What it does
GET /v1/billing Current plan, any plan change scheduled for the end of the period, and the period end.
POST /v1/billing/plan { "planId" }. Upgrades apply now and you pay the difference for the rest of the period. Downgrades apply at the end of the period.
POST /v1/billing/portal Returns { "url" } for the Stripe Customer Portal: card, invoices, tax details and cancellation.

A downgrade is refused with 409 downgrade_blocked while you use more than the smaller plan allows. details.blockers lists each limit you’re over, with how many you have and how many the plan allows. Remove those, then try again.

{
  "error": {
    "code": "downgrade_blocked",
    "message": "Current usage is over the smaller plan's limits. Remove what's listed in details, then downgrade.",
    "details": {
      "targetPlanId": "hobby",
      "blockers": [{ "limit": "projects", "current": 2, "allowed": 1 }]
    }
  }
}

Add-ons

Add-ons are only ever bought by an owner, on purpose. Nothing is added automatically.

Add-on Price What it adds How long
Extra project £5/month One more project. Usage limits stay pooled across the account. Until removed
Always-on Postgres £15/month per project Postgres never sleeps for that project, and it gets 500 CU-h of its own. Until removed
Extra seat £5/month One more team member. Until removed
Compute pack £10 200 CU-h. This billing period
Email pack £5 25,000 emails. This billing period
AI credit £10, £25 or £50 That much prepaid model usage through the AI gateway. Until used

Always-on Postgres and the compute pack need a plan with Postgres (Pro or Studio).

Request What it does
GET /v1/billing/limits Your limits now: plan plus add-ons, with per-project extras.
GET /v1/billing/add-ons Add-ons you can buy, the ones you hold, and your AI credit balance.
POST /v1/billing/add-ons { "addOnId", "quantity"?, "projectId"? }. Monthly add-ons start now and the rest of this month is charged straight away. Packs and AI credit return a Stripe Checkout url and apply once paid.
DELETE /v1/billing/add-ons/{purchaseId} Removes a monthly add-on now, with no refund for the rest of the month.

You can’t remove an add-on you’re using, such as an extra seat while every seat is filled. The request returns 409 add_on_in_use with details.blockers, as a blocked downgrade does.

If a payment fails

Stripe tries the card again over 7 days. Nothing changes while it does, apart from an email to the account’s owners and admins.

Stage When Your projects The dashboard and API
Payment failed First failed payment Work normally. Everything works.
Locked The last retry fails Read-only: files, pages and reads work, writes return 402 account_locked. Sign-in (/auth/*) still works. Reads work. Writes return 402 account_locked.
Suspended 30 days locked Not served: 403 account_suspended. Reads and export work. Writes return 403 account_suspended.
Deleted 30 days suspended Gone. Gone.

Pay the invoice from the Customer Portal (POST /v1/billing/portal) at any point before deletion and the account is back as it was within a minute. Nothing is deleted while you’re locked, and nothing is deleted without two warning emails: 7 days and 1 day before. If either warning is late, deletion moves back so there’s always at least a day after the final one.

Cancelling

Cancel from the Customer Portal. The account works normally until the end of the period you’ve paid for. It then becomes read-only for 30 days, with writes returning 402 account_cancelled, so you can export everything. After the same two warning emails, the account and all its data are deleted.

While an account is read-only

Reads keep working everywhere, so the dashboard can show what’s happening and you can export. These writes still work too:

Request Why
POST /v1/billing/portal Paying is how you get out.
POST /v1/tokens, DELETE /v1/tokens/{tokenId} The CLI and MCP export with a token; revoking access is always allowed.
DELETE /v1/members/{memberId}, DELETE /v1/members/invites/{inviteId}, POST /v1/members/leave Taking access away is always allowed.
PUT /v1/notification-preferences Your email settings.

Every other write returns the account’s error:

{
  "error": {
    "code": "account_locked",
    "message": "Payment failed, so this project is read-only. Update the card in billing to restore writes.",
    "docsUrl": "https://flatstack.dev/docs/errors/account_locked"
  }
}

GET /v1/billing shows where the account is: accountStatus (active, past_due, past_due_locked, suspended or cancelled), and lockedAt, suspendedAt, cancelledAt and deleteAfter as ISO timestamps or null.

As Markdown: api/billing.md