Initial commit: nick docs
This commit is contained in:
140
03 - API Reference/Points API.md
Normal file
140
03 - API Reference/Points API.md
Normal file
@@ -0,0 +1,140 @@
|
||||
---
|
||||
title: Points API
|
||||
tags: [api, points, reference]
|
||||
---
|
||||
|
||||
# Points API
|
||||
|
||||
Endpoints live under `/api/points/*`. The router is [`backend/src/routes/pointsRoutes.ts`](../../backend/src/routes/pointsRoutes.ts), delegating to [`PointsController`](../../backend/src/controllers/pointsController.ts) and `PointsService` ([`backend/src/services/points/PointsService.ts`](../../backend/src/services/points/PointsService.ts)). The router applies `authenticateToken` globally — every endpoint requires `Bearer JWT`.
|
||||
|
||||
Models: [[PointTransaction]], [[LevelConfig]]. Points are minted automatically by the platform (referral signup, successful purchases, reviews) and can be redeemed for discounts or marketplace credits. Levels progress as the user's lifetime points cross configured thresholds.
|
||||
|
||||
## Balance and history
|
||||
|
||||
### GET /api/points/my-points
|
||||
|
||||
**Description:** Caller's current balance, lifetime totals, current level, referral code, and progress to next level.
|
||||
**Auth required:** Bearer JWT
|
||||
**Response 200:**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"balance": 320,
|
||||
"lifetimePoints": 1280,
|
||||
"level": { "name": "silver", "tier": 2, "minPoints": 1000, "perks": [...] },
|
||||
"nextLevel": { "name": "gold", "tier": 3, "minPoints": 2500, "pointsToGo": 1220 },
|
||||
"referralCode": "ABCD1234",
|
||||
"referralsCount": 4
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### GET /api/points/transactions
|
||||
|
||||
**Description:** Paginated point ledger.
|
||||
**Auth required:** Bearer JWT
|
||||
**Query params:**
|
||||
- `page` (default 1), `limit` (default 20)
|
||||
- `type` (`earn` | `redeem` | `referral` | `purchase` | `review` | `admin_grant` | `admin_deduct`)
|
||||
- `from` / `to` (ISO dates)
|
||||
**Response 200:**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"transactions": [PointTransaction, ...],
|
||||
"pagination": { "page": 1, "limit": 20, "total": 17, "hasMore": false }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### GET /api/points/referrals
|
||||
|
||||
**Description:** Users referred by the caller plus the points earned from each.
|
||||
**Auth required:** Bearer JWT
|
||||
**Response 200:** `{ success, data: { referrals: [{ userId, name, joinedAt, pointsEarned, status }] } }`
|
||||
|
||||
### GET /api/points/levels
|
||||
|
||||
**Description:** Public list of every configured level (from [[LevelConfig]]). Used by the marketing / levels page.
|
||||
**Auth required:** Bearer JWT (but data is non-sensitive)
|
||||
**Response 200:** `{ success, data: { levels: [LevelConfig, ...] } }`
|
||||
|
||||
### GET /api/points/leaderboard
|
||||
|
||||
**Description:** Top referrers by referral count and points earned. Used for community displays.
|
||||
**Auth required:** Bearer JWT
|
||||
**Query params:** `limit` (default 10), `period` (`all` | `month` | `week`)
|
||||
**Response 200:** `{ success, data: { entries: [{ userId, name, avatar, referrals, pointsEarned }] } }`
|
||||
|
||||
## Mutations
|
||||
|
||||
### POST /api/points/redeem
|
||||
|
||||
**Description:** Redeem points for a marketplace credit / discount. Server validates available balance and configured redemption rate.
|
||||
**Auth required:** Bearer JWT
|
||||
**Request body:**
|
||||
```ts
|
||||
{
|
||||
amount: number; // points to redeem
|
||||
purpose?: "wallet_credit" | "discount_code";
|
||||
purchaseRequestId?: string; // when applying to an in-progress purchase
|
||||
}
|
||||
```
|
||||
**Response 200:**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"transaction": { /* PointTransaction */ },
|
||||
"redemption": { "creditAmount": 3.20, "currency": "USD", "code": "DISC-..." },
|
||||
"newBalance": 0
|
||||
}
|
||||
}
|
||||
```
|
||||
**Errors:** `400` insufficient balance, validation; `409` redemption already claimed.
|
||||
|
||||
### POST /api/points/generate-referral-code
|
||||
|
||||
**Description:** Generates (or rotates) the caller's unique referral code. Idempotent if the user already has one and `force` is not set.
|
||||
**Auth required:** Bearer JWT
|
||||
**Request body:** `{ force?: boolean }`
|
||||
**Response 200:** `{ success, data: { referralCode: "ABCD1234", link: "https://amn.gg/r/ABCD1234" } }`
|
||||
|
||||
The short link redirect (`GET /r/:code`) is mounted at the app root in `app.ts` and forwards to `${FRONTEND_URL}/auth/jwt/sign-up?ref=<code>`.
|
||||
|
||||
## Admin
|
||||
|
||||
### POST /api/points/admin/add
|
||||
|
||||
**Description:** Manually grant (or deduct, with negative amount) points to a user. Logged as a `PointTransaction` with `type: "admin_grant"` / `"admin_deduct"`.
|
||||
**Auth required:** Bearer JWT (admin)
|
||||
**Request body:**
|
||||
```ts
|
||||
{
|
||||
userId: string;
|
||||
amount: number; // positive = grant; negative = deduct
|
||||
reason: string; // mandatory free-text reason
|
||||
metadata?: Record<string, unknown>;
|
||||
}
|
||||
```
|
||||
**Response 200:** `{ success, data: { transaction, newBalance } }`
|
||||
**Errors:** `403` non-admin, `404` target user not found, `400` would go below zero.
|
||||
|
||||
## Side effects and real-time
|
||||
|
||||
`PointsService` emits Socket.IO events on level-up and referral rewards:
|
||||
|
||||
- `level-up` on `user-<userId>` when a transaction crosses a level threshold.
|
||||
- `referral-reward` on `user-<referrerId>` when a referred user triggers a reward.
|
||||
|
||||
See [[Socket Events]] for payload shape.
|
||||
|
||||
## Related
|
||||
|
||||
- [[PointTransaction]]
|
||||
- [[LevelConfig]]
|
||||
- [[Points and Levels Flow]]
|
||||
- [[Referral Flow]]
|
||||
- `backend/POINTS_MIGRATION.md` (legacy migration notes)
|
||||
Reference in New Issue
Block a user