mirror of
https://github.com/warmbly/warmbly.git
synced 2026-10-09 08:02:14 +00:00
feat: document the referral program guide and the referral and applied-discounts API endpoints in docs
This commit is contained in:
@@ -1820,6 +1820,31 @@ Auth: Session only (not available to API keys). Requires a selected organization
|
||||
|
||||
When invalid, `valid` is `false` and `reason` explains why.
|
||||
|
||||
### List promo-code redemptions
|
||||
|
||||
`GET /subscription/discounts`
|
||||
|
||||
Returns the organization's own promo-code redemption history, used to render the discounts list on the billing page.
|
||||
|
||||
Auth: Session only (not available to API keys). **Org permission** `manage_billing`. Requires a selected organization.
|
||||
|
||||
#### Response
|
||||
|
||||
```json
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"code": "LAUNCH20",
|
||||
"type": "percent",
|
||||
"percent_off": 20,
|
||||
"duration": "once",
|
||||
"redeemed_at": "2026-05-01T12:00:00Z"
|
||||
}
|
||||
],
|
||||
"pagination": { "next_cursor": null, "has_more": false }
|
||||
}
|
||||
```
|
||||
|
||||
### Create a billing portal session
|
||||
|
||||
`POST /subscription/portal`
|
||||
@@ -1956,6 +1981,150 @@ Auth: Session only (not available to API keys).
|
||||
}
|
||||
```
|
||||
|
||||
## Referrals
|
||||
|
||||
The referral program is per-organization. These endpoints read the caller's referral code and link, mint the code, and list the referred organizations and the earnings ledger. They power the **Settings, Referral** dashboard page. See the [referral program guide](/guides/referral-program/) for the product behavior, rewards, and clawback rules.
|
||||
|
||||
All referral endpoints are session only and require the **Manage billing** org permission, the same gate as the rest of billing. They are not reachable with an API key and there is no API permission scope for them.
|
||||
|
||||
### Get referral status
|
||||
|
||||
`GET /subscription/referral`
|
||||
|
||||
Returns the caller's referral code, share link, earnings, and conversion counts.
|
||||
|
||||
Auth: Session only (not available to API keys). **Org permission** `manage_billing`. Requires a selected organization.
|
||||
|
||||
#### Response
|
||||
|
||||
```json
|
||||
{
|
||||
"code": "K7QXMN3P",
|
||||
"share_url": "https://app.warmbly.com/register?ref=K7QXMN3P",
|
||||
"currency": "usd",
|
||||
"invitee_percent_off": 10,
|
||||
"invitee_months": 3,
|
||||
"balance_cents": 29700,
|
||||
"lifetime_earned_cents": 29700,
|
||||
"total_referred": 12,
|
||||
"pending": 5,
|
||||
"qualified": 3,
|
||||
"rewarded": 4
|
||||
}
|
||||
```
|
||||
|
||||
Amounts are in integer cents (`balance_cents` is the current credit available, `lifetime_earned_cents` is the all-time total earned). `total_referred` is the number of organizations attributed to the caller, broken down into `pending` (signed up, not yet paid), `qualified` (reached a paid checkout), and `rewarded` (the referral reward was granted).
|
||||
|
||||
### Create a referral code
|
||||
|
||||
`POST /subscription/referral`
|
||||
|
||||
Idempotently mints the caller's referral code. Calling it again returns the existing code rather than creating a new one.
|
||||
|
||||
Auth: Session only (not available to API keys). **Org permission** `manage_billing`. Requires a selected organization.
|
||||
|
||||
#### Response
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "a1b2c3d4-0000-0000-0000-000000000000",
|
||||
"owner_user_id": "9f8e7d6c-0000-0000-0000-000000000000",
|
||||
"owner_org_id": "3d11a0b2-0000-0000-0000-000000000000",
|
||||
"code": "K7QXMN3P",
|
||||
"discount_code_id": "7c6b5a40-0000-0000-0000-000000000000",
|
||||
"created_at": "2026-05-01T09:00:00Z",
|
||||
"updated_at": "2026-05-01T09:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
The share link is `https://app.warmbly.com/register?ref=<code>`. Use `GET /subscription/referral` for the prebuilt `share_url` plus earnings and counts.
|
||||
|
||||
### List referral attributions
|
||||
|
||||
`GET /subscription/referral/attributions`
|
||||
|
||||
Returns the organizations referred by the caller, newest first, with cursor pagination.
|
||||
|
||||
Auth: Session only (not available to API keys). **Org permission** `manage_billing`. Requires a selected organization.
|
||||
|
||||
| Parameter | In | Type | Description |
|
||||
|-----------|----|------|-------------|
|
||||
| `limit` | query | int | Page size. Invalid values return `400`. |
|
||||
| `cursor` | query | string | Opaque cursor from a previous `pagination.next_cursor`. |
|
||||
|
||||
#### Response
|
||||
|
||||
```json
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"id": "f00d1234-0000-0000-0000-000000000000",
|
||||
"invitee_org_id": "3d11a0b2-0000-0000-0000-000000000000",
|
||||
"status": "rewarded",
|
||||
"reward_cents": 9900,
|
||||
"reward_currency": "usd",
|
||||
"qualified_at": "2026-05-18T14:30:00Z",
|
||||
"rewarded_at": "2026-05-18T14:31:00Z",
|
||||
"created_at": "2026-05-10T09:00:00Z"
|
||||
}
|
||||
],
|
||||
"pagination": {
|
||||
"next_cursor": "o1_b3BhcXVlLWN1cnNvcg",
|
||||
"has_more": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`status` is one of `pending` (signed up, not yet paid), `qualified` (reached a paid checkout), `rewarded` (reward granted), or `void` (reversed by a clawback, self-referral, or cap). `qualified_at` and `rewarded_at` are null until those stages are reached. `reward_cents` is the credit granted for this referral, in integer cents.
|
||||
|
||||
### List referral earnings
|
||||
|
||||
`GET /subscription/referral/earnings`
|
||||
|
||||
Returns the caller's referral earnings ledger trail, newest first, with cursor pagination. Each row is a credit grant or a clawback reversal.
|
||||
|
||||
Auth: Session only (not available to API keys). **Org permission** `manage_billing`. Requires a selected organization.
|
||||
|
||||
| Parameter | In | Type | Description |
|
||||
|-----------|----|------|-------------|
|
||||
| `limit` | query | int | Page size. Invalid values return `400`. |
|
||||
| `cursor` | query | string | Opaque cursor from a previous `pagination.next_cursor`. |
|
||||
|
||||
#### Response
|
||||
|
||||
```json
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"id": "11110000-0000-0000-0000-000000000000",
|
||||
"attribution_id": "f00d1234-0000-0000-0000-000000000000",
|
||||
"amount_cents": 9900,
|
||||
"currency": "usd",
|
||||
"reason": "referral_reward",
|
||||
"balance_after_cents": 29700,
|
||||
"created_at": "2026-05-18T14:31:00Z"
|
||||
},
|
||||
{
|
||||
"id": "22220000-0000-0000-0000-000000000000",
|
||||
"attribution_id": "beef5678-0000-0000-0000-000000000000",
|
||||
"amount_cents": -2900,
|
||||
"currency": "usd",
|
||||
"reason": "referral_clawback:refund",
|
||||
"balance_after_cents": 26800,
|
||||
"created_at": "2026-05-20T10:00:00Z"
|
||||
}
|
||||
],
|
||||
"pagination": {
|
||||
"next_cursor": null,
|
||||
"has_more": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`amount_cents` is positive for a reward and negative for a clawback. `reason` is `referral_reward` or `referral_clawback:<cause>`. `balance_after_cents` is the running ledger balance after the row.
|
||||
|
||||
`type` is `credit` for a granted reward or `clawback` for a reversal within the 30-day window. `amount` is in the plan currency's major units and is negative for clawbacks.
|
||||
|
||||
## Reference data
|
||||
|
||||
Two read-only reference endpoints sit alongside billing. Unlike the rest of this group they accept any authenticated key (JWT or API key); auth only exists to keep them from being scraped.
|
||||
|
||||
@@ -171,9 +171,21 @@ These never accept an API key. They depend on a human-bound session: billing flo
|
||||
- `GET /me/danger-zone`, `POST /me/danger-zone/delete`, `DELETE /me/danger-zone/delete`
|
||||
- `GET /invitations`, `POST /invitations/accept`
|
||||
- All of `/organization/*` (create, switch, members, invitations, transfer ownership, avatar, danger zone)
|
||||
- All of `/subscription/*` (checkout, portal, cancel, change-plan, preview-change, enterprise-inquiry, etc.)
|
||||
- All of `/subscription/*` (checkout, portal, cancel, change-plan, preview-change, enterprise-inquiry, discounts, referrals, etc.)
|
||||
- All of `/admin/*`
|
||||
|
||||
### Referrals and discounts
|
||||
|
||||
The referral program and billing discount history are part of `/subscription/*`, so they are JWT only and never accept an API key. There is no API permission scope for them; browser callers are gated by the org permission below. The discount validation and checkout endpoints are listed under [Subscription and billing](/api/account-and-organization/) in the reference.
|
||||
|
||||
| Method | Path | JWT permission |
|
||||
|--------|------|----------------|
|
||||
| GET | `/subscription/referral` | `manage_billing` |
|
||||
| POST | `/subscription/referral` | `manage_billing` |
|
||||
| GET | `/subscription/referral/attributions` | `manage_billing` |
|
||||
| GET | `/subscription/referral/earnings` | `manage_billing` |
|
||||
| GET | `/subscription/discounts` | `manage_billing` |
|
||||
|
||||
## Public
|
||||
|
||||
- `GET /health`
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
"notifications",
|
||||
"security",
|
||||
"team-roles",
|
||||
"collaboration"
|
||||
"collaboration",
|
||||
"referral-program"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
---
|
||||
title: Referral program
|
||||
description: Share Warmbly, give friends a discount, and earn account credit when they upgrade.
|
||||
icon: Gift
|
||||
---
|
||||
|
||||
The referral program rewards you for bringing other teams to Warmbly. You share a personal code, the people you refer get a discount on their first few months, and when they upgrade to a paid plan you earn account credit that comes straight off your future invoices.
|
||||
|
||||
This guide covers where to find your code, what an invitee gets, what you earn, how the credit is applied, the 30-day clawback, the fraud and limit rules, and a short FAQ.
|
||||
|
||||
<Callout type="info" title="Who can manage referrals">
|
||||
The referral page lives under **Settings, Referral** and requires the **Manage billing** permission, the same permission that controls the rest of billing. The owner and any role granted billing access can open it; other members do not see it.
|
||||
</Callout>
|
||||
|
||||
## Finding your code
|
||||
|
||||
Open **Settings, Referral** in the dashboard. Warmbly mints one referral code per workspace the first time you visit, and the page shows it along with a ready-to-share link in the form:
|
||||
|
||||
```
|
||||
https://app.warmbly.com/register?ref=CODE
|
||||
```
|
||||
|
||||
Copy the link and send it to anyone you want to refer. When they open it, the code is captured automatically and carried through sign-up, so they do not have to type or remember anything.
|
||||
|
||||
The same page shows your running totals: how many people have signed up with your code, how many converted to a paid plan, and how much credit you have earned so far.
|
||||
|
||||
## What the invitee gets
|
||||
|
||||
Anyone who signs up through your link gets **10% off their first 3 months**. It is a repeating discount that is applied automatically at checkout, so the invitee does not need to enter a promo code. After the third month the discount ends and they pay the standard plan price.
|
||||
|
||||
The discount applies to whichever paid plan the invitee chooses when they upgrade. It does not require them to start on a specific plan.
|
||||
|
||||
## What you earn
|
||||
|
||||
When an invitee converts to a paid plan, you earn **account credit equal to one month-equivalent of their plan price**:
|
||||
|
||||
| Invitee's plan | Credit you earn |
|
||||
|----------------|-----------------|
|
||||
| Starter ($29/mo) | $29 |
|
||||
| Pro ($99/mo) | $99 |
|
||||
| Pro Annual | ~$99 (one month-equivalent, not the full annual invoice) |
|
||||
|
||||
Annual plans count as a single month-equivalent of the plan price, not the whole year. Referring someone who pays annually earns you roughly one month of that plan, the same as referring someone on the monthly version.
|
||||
|
||||
You earn **one reward per referred organization**, and rewards **stack across referrals**: refer five teams that all upgrade to Pro and you earn five times the Pro reward.
|
||||
|
||||
## How credit is applied
|
||||
|
||||
Credit is applied automatically. When a referred organization converts, Warmbly adds the reward to your Stripe customer balance, and that balance nets off your future Warmbly invoices. You do not need to redeem anything or contact support: the next invoice simply draws down the available credit first, and any remainder rolls forward to later invoices.
|
||||
|
||||
Because the credit lives on your billing account, you can see it reflected in the billing portal alongside your normal invoices.
|
||||
|
||||
## The 30-day clawback
|
||||
|
||||
Rewards are not final the instant they are granted. Each reward has a **30-day clawback window**: if the invitee refunds or cancels their subscription within 30 days of the reward being granted, the credit is reversed and removed from your balance.
|
||||
|
||||
This keeps the program honest and means earned credit settles once the referred subscription has held for the window. After 30 days the reward is no longer subject to clawback.
|
||||
|
||||
## Limits and fraud rules
|
||||
|
||||
To keep the program fair, a few rules apply automatically:
|
||||
|
||||
- **No self-referrals.** You cannot refer your own workspace or use your own code to claim a reward. Self-referral attempts are blocked.
|
||||
- **One reward per organization.** Each referred organization can generate at most one reward, no matter how many times its link is shared or reused.
|
||||
- **A monthly cap per referrer.** There is a per-referrer monthly limit on the number of rewarded conversions. Conversions beyond the cap in a given month still bring teams onto Warmbly, but do not add further credit that month.
|
||||
|
||||
<Callout type="warn" title="Abuse is reversible">
|
||||
Credit is provisional until the clawback window closes. Refunds, cancellations inside the window, and conversions that breach the rules above will not result in lasting credit.
|
||||
</Callout>
|
||||
|
||||
## Frequently asked questions
|
||||
|
||||
### Does the invitee need to enter a code?
|
||||
|
||||
No. The code is captured from the link (`?ref=CODE`) and carried through sign-up automatically. The 10% discount is applied at checkout without the invitee typing anything.
|
||||
|
||||
### When exactly do I earn the credit?
|
||||
|
||||
When the referred organization converts to a paid plan. Sign-ups that never upgrade do not earn a reward.
|
||||
|
||||
### What if the invitee upgrades to an annual plan?
|
||||
|
||||
You earn one month-equivalent of that plan's price, not the full annual invoice. For Pro Annual that is roughly the monthly Pro amount.
|
||||
|
||||
### Can I lose credit I already earned?
|
||||
|
||||
Only inside the 30-day clawback window. If the invitee refunds or cancels within 30 days of the reward, that reward is reversed. After the window closes the credit is settled.
|
||||
|
||||
### How many people can I refer?
|
||||
|
||||
As many as you like, and rewards stack. There is a per-referrer monthly cap on rewarded conversions, so a single month's earnings are bounded, but there is no cap on how many teams you can invite.
|
||||
|
||||
### Where does the credit show up?
|
||||
|
||||
On your Stripe customer balance, which automatically reduces your next Warmbly invoices. You can see it in the billing portal.
|
||||
|
||||
## See also
|
||||
|
||||
- [Team and roles](/guides/team-roles/) for the billing permission that controls access to the referral page.
|
||||
- [Account and organization API](/api/account-and-organization/) for the referral and discount endpoints behind this page.
|
||||
Reference in New Issue
Block a user