Get Referral Dashboard
Authenticated. Returns the user's referral link snapshot (clicks, signups, conversions, totalEarnings) plus their last 50 active rewards (clawed-back rewards excluded).
GET /api/v1/referral/dashboard โ ๐ Bearer ยท Rate limit: 30 req / minute ยท Kill-switched
Returns the user's referral dashboard payload โ link (the user's ReferralLink row with counters), rewards (last 50 active rewards, ordered newest-first; clawed-back rewards excluded), and totalEarnings (decimal as string from the link's running total).
link: null is a valid response. If the user never called GET /referral/link, no ReferralLink row exists yet, and the dashboard returns { link: null, rewards: [], totalEarnings: '0' }. Clients should call /referral/link once to bootstrap the row, or branch on link === null and render an "activate referrals" CTA.
rewards excludes clawed-back items. The filter is clawedBack: false. If admin has reversed a reward (commission clawback after a refund / chargeback / fraud), it disappears from this list. The totalEarnings snapshot on link is also adjusted by clawback flows.
Request
No body, no params.
| Header | Required | Notes |
|---|---|---|
Authorization: Bearer <accessToken> | โ | JWT from POST /auth/login |
Response
200 OK โ ApiResponseOf<ReferralDashboardResponseDto>
{
"success": true,
"data": {
"link": {
"id": "rl1a2b3c4-d5e6-7890-abcd-ef1234567890",
"code": "alice123",
"clicks": 142,
"signups": 17,
"conversions": 5,
"totalEarnings": "25.00",
"active": true
},
"rewards": [
{
"id": "rr1a2b3c4-d5e6-7890-abcd-ef1234567890",
"triggerType": "FIRST_PAYMENT",
"amount": "5.00",
"clawedBack": false,
"createdAt": "2026-04-29T20:00:00.000Z"
}
],
"totalEarnings": "25.00"
}
}Top-level fields
| Field | Type | Notes |
|---|---|---|
link | object | null | The user's ReferralLink row (see fields below). null until first /referral/link call. |
rewards | array | Last 50 active ReferralReward rows (clawedBack: false), ordered createdAt DESC |
totalEarnings | string (decimal) | Running total from ReferralLink.totalEarnings. Same value as link.totalEarnings when link is non-null โ duplicated at top level for convenience. |
link fields
| Field | Type | Notes |
|---|---|---|
id | string (UUID) | ReferralLink.id |
code | string | The shareable referral code |
clicks | number | Lifetime click counter (incremented by POST /referral/click/:code) |
signups | number | Lifetime new-user signups attributed to this code |
conversions | number | Lifetime conversion events (paid/recurring payment triggers) |
totalEarnings | string (decimal) | Running total of paid-out reward amounts (decimal as string) |
active | boolean | When false, the link is admin-disabled โ clicks still tracked but no signups/rewards record |
rewards item fields (ReferralDashboardRewardItemDto)
| Field | Type | Notes |
|---|---|---|
id | string (UUID) | ReferralReward.id |
triggerType | enum | REGISTRATION (tracking-only, amount=0) / FIRST_PAYMENT / RECURRING_PAYMENT |
amount | string (decimal) | Reward amount (decimal as string). '0' for REGISTRATION rows. |
clawedBack | boolean | Always false here (filter excludes true) |
createdAt | string (ISO 8601) | When the reward was recorded |
Errors
| HTTP | code / i18nKey | Reason |
|---|---|---|
401 | (guard) | Missing / invalid bearer token |
429 | (throttle) | Rate limit exceeded (30 req/min) |
503 | features.referral_disabled | Admin kill switch REFERRAL is active |
Side effects
prisma.referralLink.findUnique({ where: { userId } }).- Missing link โ return
{ link: null, rewards: [], totalEarnings: '0' }. No second query. prisma.referralReward.findMany({ where: { referrerId: userId, clawedBack: false }, orderBy: createdAt desc, take: 50 }).- Return
{ link, rewards, totalEarnings: String(link.totalEarnings) }.
Code samples
curl https://api.bio.re/api/v1/referral/dashboard \
-H "Authorization: Bearer $ACCESS_TOKEN"type ReferralDashboardLink = {
id: string;
code: string;
clicks: number;
signups: number;
conversions: number;
totalEarnings: string;
active: boolean;
};
type ReferralDashboardRewardItem = {
id: string;
triggerType: 'REGISTRATION' | 'FIRST_PAYMENT' | 'RECURRING_PAYMENT';
amount: string;
clawedBack: boolean;
createdAt: string;
};
type ReferralDashboard = {
link: ReferralDashboardLink | null;
rewards: ReferralDashboardRewardItem[];
totalEarnings: string;
};
async function getReferralDashboard(accessToken: string): Promise<ReferralDashboard> {
const res = await fetch('https://api.bio.re/api/v1/referral/dashboard', {
headers: { Authorization: `Bearer ${accessToken}` },
});
const json = await res.json();
if (!res.ok || !json.success) {
throw Object.assign(new Error(json?.error?.message ?? 'Dashboard fetch failed'), {
code: json?.error?.code,
});
}
return json.data;
}import { useQuery } from '@tanstack/react-query';
export const referralKeys = {
dashboard: () => ['referral', 'dashboard'] as const,
};
export function useReferralDashboard() {
return useQuery({
queryKey: referralKeys.dashboard(),
queryFn: async () => {
const res = await fetch('/api/v1/referral/dashboard');
const json = await res.json();
if (!res.ok || !json.success) {
throw Object.assign(new Error(json?.error?.message ?? 'Dashboard fetch failed'), {
code: json?.error?.code,
i18nKey: json?.error?.i18nKey,
});
}
return json.data as ReferralDashboard;
},
staleTime: 30_000,
});
}Try it
Authorization
bearer In: header
Response Body
application/json
application/json
curl -X GET "https://loading/api/v1/referral/dashboard"{
"success": true,
"data": {
"link": {
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"code": "alice123",
"clicks": 0,
"signups": 0,
"conversions": 0,
"totalEarnings": "0",
"active": true
},
"rewards": [
{
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"triggerType": "REGISTRATION",
"amount": "5.00",
"clawedBack": false,
"createdAt": "2019-08-24T14:15:22Z"
}
],
"totalEarnings": "25.00"
}
}{
"success": false,
"error": {
"code": "AUTH_UNAUTHORIZED",
"message": "Invalid credentials",
"i18nKey": "auth.login.invalid_credentials",
"i18nVars": {
"field": "email"
},
"details": [
{
"message": "email must be an email"
}
],
"correlationId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
}Source
| Source | Path | Lines |
|---|---|---|
| Controller | apps/api-core/src/modules/referral/referral.controller.ts | 58โ64 (getDashboard) |
| DTO (response) | apps/api-core/src/modules/referral/dto/referral-response.dto.ts | 367โ376 (ReferralDashboardResponseDto), 320โ361 (nested ReferralDashboardLinkDto + ReferralDashboardRewardItemDto) |
| Service | apps/api-core/src/modules/referral/referral.service.ts | 356โ365 (getDashboard) |
| Prisma models | packages/prisma/prisma/schema.prisma | ReferralLink (clicks, signups, conversions, totalEarnings, active), ReferralReward (filter clawedBack: false), enum ReferralTriggerType (REGISTRATION, FIRST_PAYMENT, RECURRING_PAYMENT) |
Track Referral Click
Public endpoint. Increments the click counter on a ReferralLink. Silent on missing/inactive codes โ the request never fails.
Apply Coupon
Authenticated. Validates a coupon code against expiry, applicability, min purchase, total / per-user usage caps under a SELECT FOR UPDATE row lock. Returns the calculated discount.