# Competitions & Teams

Base URL: `https://service.leverup.xyz`

Endpoints for trading competitions and the Genesis Airdrop team program. Useful if you are building a
community dashboard or surfacing LeverUp campaigns in your own product.

## List competitions

```http
GET /v1/trading-competition
```

| Parameter | Default | Notes |
| :--- | :--- | :--- |
| `status` | all | `UPCOMING`, `ONGOING`, `ENDED` |
| `isReadyToDisplay` | `true` | |
| `userAddress` | — | When supplied, populates `hasJoined` |

### Response

```json
[
  {
    "id": 7,
    "title": "Summer Trading Cup",
    "description": "…",
    "banner": "https://…",
    "ruleLink": "https://…",
    "ruleId": "…",
    "leaderboardType": "PNL",
    "rewardAmount": "50000",
    "rewardTokenAddress": "0x…",
    "rewardType": "TOKEN",
    "rewardDescription": "…",
    "startTime": 1785225600,
    "endTime": 1787817600,
    "currentParticipants": 1240,
    "tradingVolume": 18500000.0,
    "isReadyToDisplay": true,
    "status": "ONGOING",
    "hasJoined": false
  }
]
```

Returns a plain array, not a paginated envelope. `startTime` and `endTime` are Unix seconds.

## Competition leaderboard

```http
GET /v1/trading-competition/{id}/leaderboard
```

| Parameter | Default | Notes |
| :--- | :--- | :--- |
| `page` | `0` | |
| `limit` | `10` | Note: `limit`, not `size` |
| `orderBy` | — | A key from `headers` |
| `orderDirection` | `desc` | |

### Response

```json
{
  "headers": [
    { "key": "pnl", "label": "PnL" },
    { "key": "volume", "label": "Volume" }
  ],
  "data": {
    "content": [
      { "trader": "0x…", "stats": { "pnl": 12500.0, "volume": 890000.0 } }
    ],
    "pageNumber": 0,
    "pageSize": 10,
    "totalPages": 124,
    "totalElements": 1240
  }
}
```

Columns are dynamic. `headers` describes what each competition ranks on, and `stats` is keyed by
those same keys — render generically rather than assuming a fixed set.

```ts
const res = await fetch(`${API}/v1/trading-competition/${id}/leaderboard?limit=25`)
const { headers, data } = await res.json()

for (const row of data.content) {
  console.log(row.trader, headers.map((h) => `${h.label}: ${row.stats[h.key] ?? '-'}`).join(' | '))
}
```

## Join

```http
POST /v1/trading-competition/join
Content-Type: application/json
```

```json
{ "trader": "0x…", "inviteCode": "ABC123" }
```

Returns `200` with an empty body on success. Both fields are required and must be non-blank.

::: info No signature required
This endpoint takes an address as a parameter and does not verify wallet ownership. It registers
participation only — it cannot move funds or place trades. Do not treat it as an authentication
mechanism.
:::

## Genesis Airdrop

Team-based points program.

### Team info for a user

```http
GET /v1/genesis-airdrop/{user_address}/team-info
```

```json
{
  "leaderTeam": {
    "teamName": "Alpha",
    "code": "ALPHA1",
    "totalGeneralPoints": "125000",
    "totalDegenPoints": "42000",
    "teamMemberCount": 38,
    "latestEpochTrading": { "epoch": 6, "volumeUSD": "980000" }
  },
  "memberTeam": null
}
```

`leaderTeam` is the team the address leads; `memberTeam` is the one it belongs to. Either can be
`null`.

### Team by invite code

```http
GET /v1/genesis-airdrop/team-info-by-code/{code}
```

Returns a single `TeamInfo`, or `null` if the code is unknown.

### Team members

```http
GET /v1/genesis-airdrop/{user_address}/team-members?page=0&size=10
```

The path address is the **team leader**. Paginated.

```json
{
  "content": [
    {
      "member": "0x…",
      "joinDate": "2026-06-01T00:00:00Z",
      "cumulativeVolumeUSD": "125000",
      "cumulativeGeneralPointsToLeader": "3400",
      "cumulativeDegenPointsToLeader": "1200"
    }
  ]
}
```

### Boost history

```http
GET /v1/genesis-airdrop/{user_address}/team-boost-history?page=0&size=10
```

```json
{
  "content": [
    { "epoch": 6, "generalTeamBoostPoints": "3400", "degenTeamBoostPoints": "1200" }
  ]
}
```

### Team leaderboard

```http
GET /v1/genesis-airdrop/team-leaderboard?epoch=0&page=0&size=10
```

`epoch` defaults to `0`, meaning the current epoch.

```json
{
  "content": [
    {
      "teamName": "Alpha",
      "currentEpochVolume": "980000",
      "currentGeneralPoints": "125000",
      "currentDegenPoints": "42000"
    }
  ]
}
```
