API
Subscription upgrade API

On this page
GET /workspaces/{workspace}/subscription/upgrade
- Auth: signed-in owner.
- Name:
subscription.upgrade - Request: optional
planquery (starterorpro) and optionalintervalquery (monthoryear). - Response: the billing page for the requested paid plan. Missing, Free, Scale, or unknown plans show Starter monthly.
interval=yearopens the annual upsell. The page includes saved billing details for the workspace, or the owner’s name and email when none are saved, and the Paddle client token used to open the overlay. Opening the page does not create a payment or change the workspace subscription. - Errors: 403 for other members. 404 when the user is not a member. Guests are redirected to login.
POST /workspaces/{workspace}/subscription/checkout
- Auth: signed-in owner.
- Name:
subscription.checkout - Request:
plan(starterorpro),interval(monthoryear),first_name,last_name,address,city,state,country(two-letter code from the country list),postal,paying_for_company,company(required when paying for a company), andsave.stateis required only when that country has states, and it must be one of those states. The billing email is the workspace owner’s email. Whensaveis true, the billing profile is stored on the workspace. - Response: JSON
{ "transactionId": "txn_..." }. The billing page opens Paddle’s overlay checkout with that transaction. The card is collected there. - Errors: 403 for other members. 404 when the user is not a member. 422 when a billing field is invalid, Paddle is not configured, the price is missing, or Paddle does not return a transaction. Guests are redirected to login.
POST /workspaces/{workspace}/subscription/confirm
- Auth: signed-in owner.
- Name:
subscription.confirm - Request:
transaction_id, the Paddle transaction id from the completed checkout. - Response: JSON
{ "status": "active" }. The server reads that transaction from Paddle with the API key. Apaidorcompletedtransaction whosecustom_data.workspace_idis this workspace sets the plan, records one payment, and refreshes remaining usage. The same transaction does not record a second payment. - Errors: 403 for other members. 404 when the user is not a member. 422 when the id is malformed, Paddle cannot be read, the transaction is not paid, or it belongs to another workspace. Guests are redirected to login.
GET /workspaces/{workspace}/subscription/invoices/{transaction}
- Auth: signed-in owner.
- Name:
subscription.invoice - Response: the invoice PDF for that payment. The file name uses the Paddle transaction id.
- Errors: 403 for other members. 404 when the payment is not a completed invoice for this workspace. Guests are redirected to login.
POST /paddle/webhook
- Auth: Paddle signature (
Paddle-Signature). - Name:
billing.webhook - Request: a Paddle Billing event.
transaction.completedcarriescustom_data.workspace_idand the Paddle price id.subscription.canceledcarries the Paddle subscription id. - Response: 204. A completed payment sets the workspace plan, records one transaction, and refreshes remaining usage. The same payment notification does not record a second transaction. A canceled subscription returns the workspace to Free.
- Errors: 400 when the signature is missing or invalid.
GET /subscription/upgrade
- Auth: signed-in session.
- Request: the same optional
planandintervalquery. - Response: redirect to the workspace-scoped upgrade page for the current workspace, keeping the query. A user with no workspace is sent to create one.
- Errors: guests are redirected to login. The destination still returns 403 when the user is not the owner.
