Upgrade
Endpoint
POST /api/v1/billing/checkout start a checkout session (auth, admin, workspace-scoped)
GET /api/v1/billing/subscription fetch current subscription
POST /api/v1/billing/cancel-subscription cancel at period endHow the provider is selected
The BILLING_PROVIDER env (or Options override) decides which adapter handles checkout:
| Provider | Action |
|---|---|
stripe | Returns a Stripe Checkout session URL — you redirect the user to it. |
iyzico | Returns the Iyzico hosted-page URL. |
paytr | Returns an iframe URL for in-page checkout. |
manual | Default — no external processor. The flow creates a payment request for admin approval. |
Subscription model
typescript
{
workspace_id: ObjectId,
plan_code: string,
status: "trialing" | "active" | "past_due" | "canceled" | "expired",
trial_end: Date | null,
current_period_start: Date | null,
current_period_end: Date | null,
billing_currency: "TRY" | "USD",
billing_period: "monthly" | "yearly",
cancel_at_period_end: boolean,
provider: string, // "stripe" | "iyzico" | "paytr" | "manual"
provider_subscription_id: string | null,
provider_customer_id: string | null,
}Cancellation
POST /billing/cancel-subscription flips cancel_at_period_end to true — service continues until current_period_end, then status moves to canceled.