Skip to Content
DocumentationCI AccountBilling & Subscriptions

Billing & Subscriptions

Organizations in your CI Account have a Billing surface listing the paid add-ons that can be attached to an organization — custom domains, subdomain packs, and user support.

You cannot subscribe to anything today, and nothing can be purchased. Billing only appears on a deployment that has a live payment processor configured. No deployment has one, so the Billing tab is not rendered at all, and a direct API call to subscribe is refused with 503 BILLING_NOT_CONFIGURED. This page documents the catalog and the refusal behaviour, not a purchase flow — there is no purchase flow. See What is not available yet.

What it is

Billing is scoped to an organization, not to an individual account. Each add-on is a separate line item that an organization owner or admin would subscribe to independently.

Add-onPriceBilling interval
Custom Domains$12.00per month
Subdomain Pack$5.00per month
User Support$29.00per month

Prices are quoted in USD and are the same for every organization. There are no annual plans, tiers, or trials.

This catalog is real — it is what GET /api/organizations/:orgId/billing returns, and any member of the organization can read it. What is not real is the ability to buy any of it.

Why billing is switched off

A CI Account deployment picks its payment processor from a single secret, STRIPE_SECRET_KEY. When that secret is absent the account falls back to a mock payment processor, which reports every subscription as active while no money moves and no card is ever involved.

That fallback is fine for development and unacceptable for anything a user can reach: it hands out paid add-ons for free while recording them in the database as if they had been paid for. So the CI Account treats “no payment processor” as refuse, never as “proceed”:

  • The server reports its real capability. GET /api/organizations/:orgId/billing returns stripeEnabled, derived from the processor that would actually run the charge — not from a second, separately-read copy of the configuration.
  • The web app hides the whole surface unless that flag is exactly true. Loading, request failed, or field missing all count as “not configured”. The Billing tab trigger and its panel are not rendered — not merely disabled, because a disabled button still exists in the page and its handler is still reachable.
  • The subscribe endpoint refuses independently. The UI gate is not the control that matters; POST /api/organizations/:orgId/billing/subscriptions is reachable directly by any organization owner or admin with a session, so it checks for a live processor itself and returns 503 before touching the database.

No STRIPE_SECRET_KEY is set in any environment, so stripeEnabled is false everywhere and all three of the above are in force everywhere.

Where to find it

There is nothing to find yet. Open Organization settings on hub.ci.computer  and you will see General, Members, Invitations and Audit Log — and no Billing tab. That is the expected, correct result, not a fault with your account or your role.

For reference, this is what the surface looks like on a development build that has a payment processor configured:

Organization Settings with a Billing tab selected, showing a card for Custom Domains at $12.00 per month, Subdomain Pack at $5.00 per month and User Support at $29.00 per month, each reading No active subscription yet with a Subscribe with Stripe button

Development build only. This screenshot is here so you can recognise the surface when it ships; it is not something you can reach on hub.ci.computer, where the Billing tab is not rendered. The buttons in it have never taken a payment.

Each add-on is shown as a card with its name, its price per interval, and either the organization’s current subscription status or “No active subscription yet.” Subscribe buttons render for organization owners and admins only; members see the cards without buttons.

What happens if you try to subscribe anyway

The web app gives you no way to start, so this only applies to calling the API directly.

POST /api/organizations/:orgId/billing/subscriptions returns:

HTTP/1.1 503 Service Unavailable Content-Type: application/json { "error": "Billing is not available on this deployment", "code": "BILLING_NOT_CONFIGURED" }

The check runs before anything is written, so a refused attempt leaves no subscription row and no org.billing.subscribe audit entry. The attempt is recorded in the deployment’s server logs only.

Treat BILLING_NOT_CONFIGURED as terminal rather than transient. Despite the 503, retrying will not help — the response means the deployment has no payment processor, and nothing about it changes until an operator configures one.

For developers

Two endpoints back the Billing surface. Both are scoped to an organization you are a member of; requests for organizations you do not belong to return 404.

MethodPathWho can call itToday’s behaviour
GET/api/organizations/:orgId/billingany member of the organization200 with stripeEnabled: false, the catalog, and []
POST/api/organizations/:orgId/billing/subscriptionsowner or admin only503 BILLING_NOT_CONFIGURED — always, on every deployment

GET .../billing returns the add-on catalog, the organization’s current subscriptions, and stripeEnabled — whether a live payment processor is configured. A client deciding whether to offer a purchase must read stripeEnabled and require a literal true; a missing field means an older deployment that predates the flag and must be treated as not configured.

POST .../billing/subscriptions takes a featureKey (custom_domain, subdomain_pack, or user_support) and an optional quantity between 1 and 100. On a deployment with a live processor it returns 201 with the stored subscription; on every current deployment it returns 503 as above.

Configuration

These apply to whoever operates the CI Account deployment — not to end users. Names only; never commit or paste the values.

NameKindPurpose
STRIPE_SECRET_KEYsecretThe switch. Present and non-blank ⇒ billing is offered; absent ⇒ the surface is hidden and subscribe returns 503.
STRIPE_PRICE_CUSTOM_DOMAINvariablePrice identifier for the Custom Domains add-on
STRIPE_PRICE_SUBDOMAIN_PACKvariablePrice identifier for the Subdomain Pack add-on
STRIPE_PRICE_USER_SUPPORTvariablePrice identifier for the User Support add-on

None of these are set in any environment today. They must reach the CI Account worker as runtime secrets — a value stored only as a CI/CD repository secret never reaches the running worker, and the deploy pipeline does not sync them. Setting STRIPE_SECRET_KEY is what turns the Billing surface on, so it should not be set until the gaps in What is not available yet are closed.

What is not available yet

This list is exhaustive as of this page’s last update. Assume anything not described above does not exist.

  • No purchase, at all. Billing is not offered on any deployment, and the subscribe endpoint refuses every request.
  • No payment method collection. There is no Stripe Checkout, no card form, and no client-side Stripe integration, so no payment could be taken even if the surface were enabled.
  • No provider callbacks. There is no webhook endpoint of any kind. Subscription state would be written once, when the button is clicked, and never updated — payment success or failure, dunning, cancellation and refunds would all be invisible to the CI Account.
  • No cancellation or downgrade. There is no way to cancel or reduce a subscription from the UI or the API.
  • No invoices, receipts, or billing portal. There is no invoice history and no link to a payment-processor customer portal.
  • No entitlement enforcement. A subscription grants, unlocks and limits nothing. Custom Domains does not check whether you are subscribed — it is in development and unusable for other reasons entirely.
  • No quantity control. The web app has no seat or pack picker.
  • Not on hub.ci.computer. The production CI Account does not carry the Billing surface at all — it is not a matter of the tab being hidden there, the code is not deployed.

Troubleshooting

IssueCause / fix
No Billing tab in organization settingsExpected everywhere today. The deployment has no payment processor configured, so the tab is not rendered. It is not a permissions problem — owners and admins do not see it either.
503 with code: BILLING_NOT_CONFIGURED from the APIExpected everywhere today. Terminal, not transient: retrying cannot succeed until an operator configures a payment processor.
Billing tab appears, then disappearsThe billing request failed after first render. The surface fails closed on any error, so it hides itself rather than offering a purchase it cannot honour. Check the browser network log.
Add-on cards load but there is no buttonYou are a member. Only owners and admins get subscribe buttons, even where billing is configured.
An older build shows a Billing tab and reports activeThat build predates the billing gate and is using the mock payment processor. The subscription is not real, no payment occurred, and nothing was purchased. Do not treat it as an entitlement.
404 from either endpointYou are not a member of that organization.

Limits

Applicable once a payment processor is configured; none of it is reachable today.

  • One subscription per organization per add-on
  • Quantity is capped at 100 by the API
  • USD and monthly billing only
  • Prices are fixed in the catalog — no discounts, coupons, or custom pricing

See also: Organizations, Custom Domains.

Last updated on