Billing & Usage Plans
Billing & Usage Plans
Section titled “Billing & Usage Plans”Dewee integrates with Polar.sh (packages/dewee-commercial/) for workspace billing:
- Self-Service Checkout: Workspace owners upgrade via Polar checkout sessions.
- Quota Enforcement: Hard and soft token limits enforced per tenant workspace.
Complimentary access grants
Section titled “Complimentary access grants”A platform super admin can give a workspace or a person the Annual plan for a fixed number of days at no charge. A grant is separate from billing: it creates no Polar subscription, no order, and no revenue record, and every change is audited.
- Hosted workspace (
shared_saas): the workspace runs on Annual until the grant ends. The billing page shows the plan as Complimentary with its end date. - Self-install license (
self_install): the recipient claims a real license key that activates like a paid self-install key. Activation, heartbeat, and offline grace all stop at the grant end. - Dedicated and on-premises runtimes cannot be granted; they need provisioned, paid infrastructure.
A grant for a user or an email address is claimed with a one-time claim token that the operator delivers privately. The signed-in recipient must match: for an email grant, the account’s email must be verified and equal to the granted address.
Which plan applies
Section titled “Which plan applies”When several facts exist, the hosted workspace uses the first that applies:
- An operator security hold, which a grant never overrides.
- A paid subscription that is active or trialing.
- A complimentary grant in effect.
- Otherwise the subscription state, or Free when there is none.
So a refund or cancellation does not end a grant early, and a grant ending does not restore a refunded subscription. If the subscription had already lapsed, the workspace returns to Free when the grant ends, with no data purge scheduled by the grant ending.
Expiry
Section titled “Expiry”Grant expiry is checked whenever the workspace’s plan is read, and a scheduled sweep catches workspaces that are idle, including grants revoked or issued since the workspace was last read, within 15 minutes. Revoking a grant removes hosted access at once; a self-install runtime loses it at its next heartbeat, or when its offline grace runs out, which is never later than the grant end.
Operators manage grants with dewee admin access-grants.
Discount Codes
Section titled “Discount Codes”Dewee runs discount campaigns for two products: the self-install licence and the hosted annual plan. A campaign is either applied automatically (Early Access) or redeemed with a code the customer enters. Dewee validates every code itself and then opens a Polar checkout that already carries the discount; Polar’s own discount-code field is turned off, and Polar confirms the final price, including tax, at checkout.
Discounts never combine. A code replaces any automatic discount, and only the first purchase uses a discount: renewals are charged at the regular price.
Codes are case-insensitive, and spaces and dashes are ignored, so spring-26 and SPRING26 are the same code. A valid code is 3 to 64 letters or digits.
Self-install licence
Section titled “Self-install licence”Buyers enter a code at /buy/license/code. The page shows the list price, the discount and the estimated total before tax, then continues to Polar. If Polar does not accept the discount at that point, the page says so and nothing is charged: the buyer can choose to buy at the standard price or try another code. /buy/license remains the one-click checkout with the automatic Early Access discount.
To check a code without starting a checkout, send a same-origin request:
POST /api/billing/self-install/promo-codeContent-Type: application/json
{ "code": "SPRING26" }{ "valid": true, "campaign": { "displayName": "Spring offer", "discountType": "percentage", "discountPercent": 20, "discountAmountCents": null }, "listPriceCents": 50000, "estimatedPriceCents": 40000, "currency": "usd"}discountPercent is set for a percentage discount and discountAmountCents for a fixed one; the other is null. The code page and this endpoint share a budget of 10 attempts per IP per hour. Both are available on the hosted edition only.
Hosted annual plan
Section titled “Hosted annual plan”Anyone with billing management permission on the workspace can add promoCode to the checkout request:
POST /api/workspaces/<workspaceId>/billing/checkoutContent-Type: application/json
{ "planCode": "annual", "promoCode": "SPRING26" }The response is the usual checkout (checkoutId, checkoutUrl, checkoutStatus, expiresAt) plus a discount object with displayName, listPriceCents and estimatedPriceCents. An empty or missing promoCode starts a regular checkout.
To price a code first, without reserving a checkout:
POST /api/workspaces/<workspaceId>/billing/promo-codeContent-Type: application/json
{ "promoCode": "SPRING26" }It answers with the same body as the self-install check above. A code is evaluated for that workspace and for the signed-in user’s verified email. Checkout and validation share a budget of 10 code attempts per workspace per hour.
If a checkout is already open for the workspace with a different code, or with no code, a request with a code answers 409 billing_checkout_in_progress instead of reusing a checkout priced differently. Finish that checkout or wait for it to expire.
Error codes
Section titled “Error codes”A refused code answers 422 with a stable error code; nothing is reserved or charged:
{ "error": "promo_code_expired", "message": "This promo code has expired.", "details": { "reason": "expired" } }| Error code | Meaning |
|---|---|
| promo_code_invalid | Unknown code, or a campaign that is disabled or has not started yet. |
| promo_code_expired | The campaign has ended. |
| promo_code_exhausted | Every redemption has been used. |
| promo_code_product_ineligible | The code belongs to the other product. |
| promo_code_customer_ineligible | The code is reserved for specific customers or workspaces, or for new customers only. Anonymous self-install buyers never match a customer restriction. |
| promo_code_already_redeemed | This customer (email or workspace) has already used the code. |
The customer app and the code page show these in English and Vietnamese, keyed by the same error codes. Too many attempts answer 429 rate_limit_exceeded.