Billing API

monetr's hosted service charges for itself through Stripe, and these three endpoints are how the app hands you off to Stripe and picks you back up afterwards. monetr never sees a card number: both endpoints that matter return a Stripe URL for the browser to go to.

Hosted only

These endpoints are part of monetr's paid hosted service. If you're self-hosting with billing disabled, all three return 404 with {"error": "billing is not enabled"}. That's a hard check at the top of each handler, before anything else happens.

Not for API keys

All three reject API keys. They're reachable only from the monetr web app while signed in. A long lived credential shouldn't be able to start a subscription or open a billing portal on its own.

POST Start a checkout

Creates a Stripe checkout session and returns where to send the browser.

In the app: The subscribe button on the "your subscription isn't active" screen.

POST /api/billing/create_checkout

Auth: Not available to API keys.

Body

AttributeTypeRequiredDescription
cancelPathstring, nullableNoWhere to drop the user back in monetr if they abandon Stripe's checkout. Leave it out and Stripe uses monetr's default.

Errors

StatusWhen
400The account already has an active subscription, or already has a subscription of any kind. Those are separate errors with different messages, since a lapsed subscription needs the portal rather than a new checkout.
404Billing isn't enabled on this server.

GET Finish a checkout

Called when Stripe sends the user back to monetr. It checks with Stripe whether the payment actually went through and updates the account, then tells the client where to go.

In the app: The page Stripe redirects to after checkout, which reads the answer and either lets you in or sends you back to subscribe.

GET /api/billing/checkout/:checkoutSessionId

Auth: Not available to API keys.

Path parameters

AttributeTypeRequiredDescription
checkoutSessionIdstringYesStripe's checkout session identifier, from the redirect. This is a Stripe ID, not a monetr ULID.

Responses

Payment went through:

{
  "nextUrl": "/",
  "isActive": true
}

It didn't, or hasn't yet:

{
  "message": "Subscription is not active.",
  "nextUrl": "/account/subscribe",
  "isActive": false
}

Both are 200. Check isActive, not the status code. An inactive answer isn't necessarily failure either, Stripe's webhook may not have landed yet.

Errors

StatusWhen
400checkoutSessionId is empty.
404Billing isn't enabled on this server.

GET Open the billing portal

Returns a URL to Stripe's billing portal, where someone can change their card, see invoices or cancel.

In the app: The manage subscription button on the subscription settings page.

GET /api/billing/portal

Auth: Not available to API keys.

Response

{
  "url": "https://billing.stripe.com/p/session/live_YWNjdF8xTTJKVGtMa2RJd0h1N2l4"
}

Send the browser there. The link is short lived and single use, so fetch a fresh one each time rather than storing it.

Errors

StatusWhen
400The account has no subscription at all, so there's no portal to open. Start a checkout instead.
404Billing isn't enabled on this server.