> ## Documentation Index
> Fetch the complete documentation index at: https://docs.d-sports.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Fan Rep API

> Ledger-backed Fan, Club, Player, and D-Sports Direct Rep totals, breakdown, and client-safe earns.

## Scope

Fan Rep is an append-only ledger (`RepLedgerEntry`) separate from quest points and leaderboard scores. Clients read aggregates and a paginated ledger. Only a narrow set of social actions may earn through the generic earn route.

## Endpoint map

* `GET /api/v1/engage/rep/breakdown` — totals by source plus per-team Club Rep subtotals
* `GET /api/v1/engage/rep/ledger` — keyset-paginated ledger
* `POST /api/v1/engage/rep/earn` — client-safe earn (`reaction`, `message`, `pollVote`, `share` only)
* `GET /api/v1/engage/rep/me` — Club Rep per team
* `GET /api/v1/engage/rep/player/me` — Player Rep per player
* `POST /api/admin/users/{userId}/rep` — platform-admin D-Sports Direct grant (redacted internals)

Related routes that write Rep themselves (do not also call `/earn`):

* `POST /api/v1/engage/quests/arena-check-in`
* Daily-quest session complete paths under `/api/v1/engage/quests/*`

## Breakdown contract

`GET /api/v1/engage/rep/breakdown` returns:

| Field              | Meaning                                      |
| ------------------ | -------------------------------------------- |
| `totalFanRep`      | Sum of all four source fields                |
| `fanAmpRep`        | `repType = Fan`                              |
| `clubRep`          | `repType = Club`                             |
| `playerAmpRep`     | `repType = Player`                           |
| `dsportsDirectRep` | `repType = Direct` (admin grants today)      |
| `clubRepByTeam`    | Club totals that resolve to a real `Team` id |

Amount and `repType` are server-authoritative. Clients must not invent source splits.

## Ledger contract

* Keyset pagination on `(createdAt DESC, id DESC)`.
* `source` is `fanAmp` | `club` | `playerAmp` | `dsportsDirect`.
* `playerChallenge` maps to `source=playerAmp`.
* Direct grants map to `source=dsportsDirect`. Ledger rows may include an optional stored `reason`.

## Earn contract

* `POST /api/v1/engage/rep/earn` accepts only `reaction`, `message`, `pollVote`, and `share`.
* Direct kinds (`adminGrant`, `referralBonus`, `eventReward`) on `/earn` return `403`.
* Arena check-in and daily-quest Rep use their dedicated routes.
* Unauthorized requests return `401`.

## D-Sports Direct grants

* The live producer is `POST /api/admin/users/{userId}/rep` (`isAdmin` only).
* Body: `{ amount: integer 1–100000, reason?: string max 200 }`.
* Each POST is a new grant. The server generates the idempotency key.
* `referralBonus` and `eventReward` are reserved Direct kinds with no writer yet.
* Native admin Coins UI for this grant is follow-up work, not the contract.

## Deep-dive documentation

* [Fan Rep overview](/repositories/d-sports-api/fan-rep/index)
* [Architecture](/repositories/d-sports-api/fan-rep/architecture)
* [Behavior](/repositories/d-sports-api/fan-rep/behavior)
