# Get IGP24 team placements

```http
GET /api/public/v1/competitions/{competitionId}/leaderboard/teams/{teamId}/placements
```

**Scope**: `competition.read`.

Returns one IGP24 team's public scoring placements. The response never includes user identities, email addresses, member identities, or submitted polynomial coefficients.

This endpoint is available only when `submissionSpec.kind` is `igp24-polynomial`. Before leaderboard publication it returns an empty, unpublished response without querying placement data.

## Parameters

| Parameter | Location | Type | Required | Default | Description |
| :--- | :--- | :--- | :---: | :--- | :--- |
| `competitionId` | path | string | Yes | — | IGP24 competition ID. Use `igp24`. |
| `teamId` | path | string | Yes | — | Team ID from an IGP24 leaderboard entry or leaderboard search result. |
| `cursor` | query | string | No | — | Opaque cursor returned as `nextCursor` by the previous page. |
| `limit` | query | integer | No | `25` | Page size from `1` through `100`. |

## Response DTO

```ts
type GetIgp24TeamPlacementsResponse = {
  ok: true;
  data: {
    teamId: string;
    placements: Igp24Placement[];
    nextCursor: string | null;
    totalPlacements: number;
    meta: Igp24PublicationMeta;
  };
};

type Igp24PublicationMeta = {
  published: boolean;
  publishedAt: string | null;
};

type Igp24Placement = {
  t: number;
  r: number;
  label: string;
  points: number;
  kTeams: number;
  scoringDiscAbs: string;
  minScoringDiscAbs: string;
  discSource: 'exact_nfdisc' | 'mixed_disc';
  isSolvable: boolean | null;
  baselineUnlocked?: boolean;
  baselineDiscAbs?: string | null;
};
```

## Response fields

| Field | Type | Description |
| :--- | :--- | :--- |
| `teamId` | string | Team whose placements were requested. |
| `placements[]` | `Igp24Placement[]` | Current page, ordered by points descending and then by `t` and `r` ascending. |
| `nextCursor` | string \| null | Cursor for the next page, or `null` when this is the final page. |
| `totalPlacements` | integer | Total number of public placements held by the team across all pages. |
| `meta.published` | boolean | Whether the leaderboard is published. |
| `meta.publishedAt` | string \| null | ISO 8601 UTC publication time, or `null` before publication. |

### `Igp24Placement`

| Field | Type | Required | Description |
| :--- | :--- | :---: | :--- |
| `t` | integer | Yes | Transitive group index. |
| `r` | integer | Yes | Real-root count/signature. |
| `label` | string | Yes | Transitive group label, for example `24T105`. |
| `points` | number | Yes | Points credited to this team for the pair, rounded to six decimal places. |
| `kTeams` | integer | Yes | Number of participant teams credited for this pair. |
| `scoringDiscAbs` | string | Yes | Team's absolute scoring discriminant, represented as a decimal string to preserve integer precision. |
| `minScoringDiscAbs` | string | Yes | Minimum absolute scoring discriminant currently credited for the pair. |
| `discSource` | `exact_nfdisc` \| `mixed_disc` | Yes | Source used for the scoring discriminant. |
| `isSolvable` | boolean \| null | Yes | Known solvability flag for the label, or `null` when unavailable. |
| `baselineUnlocked` | boolean | No | Present when baseline information is exposed for this placement. |
| `baselineDiscAbs` | string \| null | No | Absolute baseline discriminant, represented as a decimal string; may be `null` when no value is available. |

## Example

```bash
curl "https://api.sair.foundation/api/public/v1/competitions/igp24/leaderboard/teams/teamv2_public/placements?limit=25" \
  -H "Authorization: Bearer $SAIR_API_KEY"
```

```json
{
  "ok": true,
  "data": {
    "teamId": "teamv2_public",
    "placements": [
      {
        "t": 105,
        "r": 12,
        "label": "24T105",
        "points": 1,
        "kTeams": 1,
        "scoringDiscAbs": "100",
        "minScoringDiscAbs": "100",
        "discSource": "exact_nfdisc",
        "isSolvable": true,
        "baselineUnlocked": true,
        "baselineDiscAbs": "120"
      }
    ],
    "nextCursor": null,
    "totalPlacements": 1,
    "meta": {
      "published": true,
      "publishedAt": "2026-05-19T00:00:00Z"
    }
  }
}
```

## Before publication

```json
{
  "ok": true,
  "data": {
    "teamId": "teamv2_public",
    "placements": [],
    "nextCursor": null,
    "totalPlacements": 0,
    "meta": {
      "published": false,
      "publishedAt": null
    }
  }
}
```

## Errors

| HTTP | Code | When |
| :---: | :--- | :--- |
| `400` | `MALFORMED_BODY` | `limit` cannot be parsed, is outside `1..100`, or `cursor` is invalid. |
| `404` | `NOT_FOUND` | The competition is unavailable or is not an IGP24 competition. |

See [Errors](../../../errors.md) for authentication, authorization, and common errors.
