MegalaniaDocs
Docs menu
  1. Docs
  2. Reference
  3. Billing
Reference

Billing

llms.txt

POST /v1/account/checkout

Open a Stripe payment page that adds credits to this account.

Owner only. A pack tops up an active subscription, and only the packs of your plan are on sale; without one the answer is 409 no_subscription. The credits land on this account once Stripe confirms the payment. It makes no keys. Open checkout_url in a browser; the page expires after 30 minutes. ref_token and ref_code are read on every checkout, but only the account’s first paid purchase binds a referral (MEG-504). A bad ref is dropped, never an error. Stripe sends the buyer back to the dashboard: /buy?paid, or /buy?cancelled.

Parameters

name in required type or values what it is
Idempotency-Key header no string Your own id for this call, 1 to 128 printable ASCII characters. A second call with the same key from the same account key inside 24 hours answers 200 with the same checkout_url, and opens no new payment page. A call that failed frees its key.

Body

field required type or values what it is
pack yes string The pack’s public name, like starter. A name we do not sell is 404 not_found.
campaign no string Where the buyer came from, like reddit-launch. Never a URL or an email.
ref_token no string Added by MEG-237. The ref_token the /r/{code} link put on the page’s address. Checked with our secret; a bad, forged or expired one (older than 60 days) is dropped without an error. Binds only on the account’s first paid purchase.
ref_code no string Added by MEG-237. A referral code typed by the buyer, 8 of a-z and 0-9. An unknown code is dropped without an error. ref_token wins when both are sent.

Answers

status what it means
200 The Stripe payment page. Open checkout_url in a browser. It expires after 30 minutes.
400 bad_parameter: pack is missing (field pack), campaign is wrong (field campaign), Idempotency-Key is not 1 to 128 printable ASCII characters (field Idempotency-Key), or a key this request does not take (field names it). bad_request: the body is not one JSON object.
401 bad_token. The key is missing, not valid, expired, revoked, of an unknown prefix or wrong length, or sent as the api_key query parameter, which no route accepts.
403 wrong_scope (a scrape key on a route that needs an account key, or an account key on a scraping or batches route) or owner_only (your role is member).
404 not_found. No pack with that name.
413 body_too_large. The body was larger than 4 KiB.
415 unsupported_media_type. Send Content-Type: application/json, even for an empty {} body.
422 idempotency_mismatch. This Idempotency-Key already opened a checkout for a different body. Send the same body, or a new key.
429 rate_limited. Too many requests to this endpoint right now. Wait Retry-After seconds, then send the same request again.
500 internal. Our bug. Try again in a minute; if it stays, report the X-Request-Id.
503 checkout_failed (Stripe did not open the payment page; nothing was charged, try again in a minute), checkout_closed (buying is off on this server) or busy (the account store is not configured, or a request with this Idempotency-Key is still opening its page; send it again in a few seconds).

POST /v1/account/subscription

Subscribe to a plan, or change it.

Owner only. With no subscription, opens a Stripe payment page for the plan. With one, moves to the plan: a higher plan is charged in full now and starts a new month with its full credits; a lower plan starts at your next renewal. Two identical changes sent at once are charged once. Credits come only with a paid invoice. Packs top up a subscription (POST /v1/account/checkout).

Body

field required type or values what it is
plan yes string

Answers

status what it means
200 New subscription: checkout_url, a Stripe payment page that expires after 30 minutes. Stripe sends you back to /plan?subscribed or /plan?cancelled. A plan change: change is upgrade (paid now, the month restarts, the new credits land when Stripe confirms) or downgrade (from your next renewal; no money moves now).
400 bad_parameter: plan is missing or not a plan (field plan). bad_request: the body is not one JSON object.
401 bad_token. The key is missing, not valid, expired, revoked, of an unknown prefix or wrong length, or sent as the api_key query parameter, which no route accepts.
402 payment_failed. The payment for the higher plan failed. Your plan did not change.
403 wrong_scope (a scrape key on a route that needs an account key, or an account key on a scraping or batches route) or owner_only (your role is member).
409 checkout_open (a payment page is still open), past_due (the last payment failed; update the card in the billing portal) or already_on_plan.
413 body_too_large. The body was larger than 4 KiB.
415 unsupported_media_type. Send Content-Type: application/json, even for an empty {} body.
429 rate_limited. Too many requests to this endpoint right now. Wait Retry-After seconds, then send the same request again.
500 internal. Our bug. Try again in a minute; if it stays, report the X-Request-Id.
503 checkout_failed (Stripe did not answer; nothing was charged, try again in a minute) or checkout_closed (buying is off on this server).

POST /v1/account/billing-portal

Open the Stripe billing portal.

Owner only. Your card, your invoices, and canceling.

Answers

status what it means
200 portal_url, a Stripe page for your card, your invoices and canceling. A cancel takes effect at the end of the paid month; your credits stay until they expire.
401 bad_token. The key is missing, not valid, expired, revoked, of an unknown prefix or wrong length, or sent as the api_key query parameter, which no route accepts.
403 wrong_scope (a scrape key on a route that needs an account key, or an account key on a scraping or batches route) or owner_only (your role is member).
404 not_subscribed. This account has no subscription yet.
429 rate_limited. Too many requests to this endpoint right now. Wait Retry-After seconds, then send the same request again.
500 internal. Our bug. Try again in a minute; if it stays, report the X-Request-Id.
503 checkout_failed (Stripe did not answer) or checkout_closed (buying is off on this server).

GET /v1/plans

The free tier and the plans you can subscribe to.

No key. From the plan rows in Postgres; the price is the one Stripe charges.

Answers

status what it means
200 The free tier first, then the plans you can subscribe to, cheapest first. price is per month, in currency; both are null on the free tier, which needs no subscription.
500 internal. Our bug. Try again in a minute; if it stays, report the X-Request-Id.
503 Error. The code is in the body.