RTFC API

Payments

Costs & quotas covers what a plan includes and how usage is metered. This page covers actually paying for one: Stripe Checkout for the subscription, the Customer Portal for self-service management, and how overage is billed.

Subscribing

bash
curl -sX POST $RTFC/billing/checkout-session \
  -H "X-Auth-Token: $TOKEN" -H "Content-Type: application/json" \
  -d '{"plan_slug": "pro"}'
json
{"checkout_url": "https://checkout.stripe.com/c/pay/cs_..."}

Redirect the user to checkout_url - Stripe's own hosted Checkout page. The plan is resolved server-side from plan_slug; there is no way to pass a price or plan id directly, so a client can never check itself out onto a plan it wasn't offered. 404 for an unknown plan_slug or one with no Stripe price attached (the free plan never has one - there is nothing to pay for it).

Checkout collects the card, the billing address, and a VAT number where applicable - EU VAT is calculated automatically. On completion Stripe sends a webhook that activates the subscription; poll GET /subscriptions/me (or watch for the plan to change) rather than trusting the checkout redirect alone, since the webhook can arrive a moment after the browser returns.

Managing an existing subscription

bash
curl -sX POST $RTFC/billing/portal-session -H "X-Auth-Token: $TOKEN"
json
{"portal_url": "https://billing.stripe.com/p/session/..."}

Redirect to portal_url - Stripe's Customer Portal: update the card, download invoices, or cancel. 404 if the caller has never checked out (no billing account on file yet).

Overage

A plan whose overage_allowed is true (see Costs & quotas) bills usage past the included allowance as metered overage on the next invoice, in EUR - converted from the underlying USD spend at the exchange rate pinned for the day the usage happened, not the day it's billed. Overage for a day is only reported once that day has fully settled, so it will not appear until the following day at the earliest.

Subscription status

bash
curl -s $RTFC/subscriptions/me -H "X-Auth-Token: $TOKEN"
json
{"plan": {"slug": "pro", "name": "Pro"}, "status": "past_due", "...": "..."}

status is trialing, active, past_due, or canceled. A failed payment moves the subscription to past_due - you'll also get an email - and Stripe retries automatically; if every retry fails the subscription is canceled and the account reverts to the free plan. Nothing is lost: claims already in flight keep running, and detected claims are held (not dropped) if the account is over its free-plan allowance in the meantime, then processed once you resubscribe or the next period starts.