# List Contributor Network items

```http
GET /api/public/v1/contributor-network/items
```

**Scope**: `contributor-network.read`.

Lists active public items across supported competitions. Reading the collection requires neither competition enrollment nor account setup.

For a known resource type, send both `competitionId` and `kind` and use its competition guide for the exact summary shape. Omit either discriminator only when the client intentionally handles every shape that can match the broader query.

## Query parameters

| Parameter | Type, requirement, default, and meaning |
| :--- | :--- |
| `competitionId` | **Optional string.** Exact competition ID. The competition must be publicly visible and expose Contributor Network items. |
| `kind` | **Optional string.** Exact, case-sensitive discriminator: `cheatsheet`, `solver-template`, `model-reference`, or `lean-kernel-package`. |
| `scope` | **Optional string.** `all` (default), `mine`, or `favorites`. |
| `track` | **Optional string.** Stage 2 track ID; valid only with `kind=solver-template`. |
| `problemId` | **Optional string.** Exact Problem ID frozen into a Lean package; valid only with `kind=lean-kernel-package`. |
| `search` | **Optional string.** Trimmed, non-empty text of at most 200 characters. Searches public author, title, remark, and kind-specific public content. |
| `publicCode` | **Optional string.** Human-shareable code. Surrounding whitespace is removed and ASCII letter case is ignored. |
| `sort` | **Optional string.** `newest` (default) or `earliest`. |
| `cursor` | **Optional string.** Opaque cursor returned by the preceding page. |
| `limit` | **Optional integer.** Page size from `1` through `100`; defaults to `25`. |

`scope=mine` selects items authored by the API key owner. `scope=favorites` selects items favorited by that account; it still requires only the read scope.

`search` is a case-insensitive substring match over the public author display name, title, remark, and the immutable public content represented by the item: cheatsheet text, solver source, the model repository and commit, or Lean Workspace paths and text. It never searches private source resources, withdrawn content, opaque item IDs, or external repository contents. Matching content is not copied into the list response; fetch the item detail to read it.

`problemId` compares the immutable value stored with a publication. It is not revalidated against the current Problem catalog, so a valid historical or unmatched value returns an empty collection.

Unknown query parameters, repeated single-value parameters, blank filter values, and kind-specific filters without their required `kind` return `422 RESOURCE_FIELD_INVALID`.

When `publicCode` is present, all other supplied filters still apply. The response contains at most one item and `nextCursor` is `null`; combining `publicCode` with `cursor` returns `422 RESOURCE_FIELD_INVALID`. A code that does not identify an active item matching the filters returns an empty collection.

## Ordering and pagination

`newest` orders by `publishedAt` descending; `earliest` orders ascending. Item ID is the stable tie-breaker in both directions. Filters are applied before the page boundary.

The opaque cursor is bound to the API key owner, this endpoint, all normalized filters, and the sort direction. Reusing it with a different request returns `400 MALFORMED_BODY`. Pagination is not a frozen snapshot: items published or withdrawn during a traversal can affect later pages, so long-running clients should de-duplicate by `id`. See [Pagination](../../pagination.md).

## Example request

```bash
curl "https://api.sair.foundation/api/public/v1/contributor-network/items?competitionId=mathematics-distillation-challenge-equational-theories-stage1&kind=cheatsheet&scope=favorites&limit=25" \
  -H "Authorization: Bearer $SAIR_API_KEY"
```

## Response

Returns `200 OK` with:

| Field | Type | Description |
| :--- | :--- | :--- |
| `items` | `ContributorNetworkItemSummary[]` | Discriminated union of kind-specific summaries. |
| `nextCursor` | string \| null | Cursor for the next page, or `null` after the final page. |

### Common summary fields

| Field | Type | Description |
| :--- | :--- | :--- |
| `id` | string | Stable, opaque Contributor Network item ID. |
| `publicCode` | string | Immutable human-shareable code. Use `id` for resource paths. |
| `competitionId` | string | Competition that owns the publication. |
| `kind` | string | Discriminator that selects the kind-specific summary shape. |
| `title` | string | Title snapshotted for this immutable publication. |
| `remark` | string \| null | Optional publication note. |
| `author.sairId` | string | Public SAIR account ID. |
| `author.displayName` | string | Public display name snapshotted for the publication. |
| `author.avatarUrl` | string \| null | Public avatar URL, or `null` when absent. |
| `favoriteCount` | integer | Accounts currently favoriting the item. |
| `viewerHasFavorited` | boolean | Whether the API key owner currently favorites the item. |
| `commentCount` | integer | Visible comments currently attached to the item. |
| `directChildCount` | integer | Active items that directly reference this item as their parent. |
| `publishedAt` | string | ISO 8601 UTC publication time. |

Kind-specific summary fields are documented by the selected guide:

- [Stage 1 cheatsheet summary](../competitions/mathematics-distillation-stage1/list-contributor-cheatsheets.md#summary-fields)
- [Stage 2 solver-template summary](../competitions/mathematics-distillation-stage2/list-contributor-solvers.md#summary-fields)
- [Modular Arithmetic model-reference summary](../competitions/modular-arithmetic-challenge/list-contributor-models.md#summary-fields)

The list never includes source content, content excerpts, Workspace file paths, or private source IDs. Kind-specific fields that do not apply are omitted instead of returned as `null`.

An empty match returns `items: []` and `nextCursor: null` with `200 OK`. Successful responses use `Content-Type: application/json` and `Cache-Control: private, no-store` because `viewerHasFavorited` is caller-specific.

## Errors

| HTTP | Code | When |
| :---: | :--- | :--- |
| `400` | `MALFORMED_BODY` | The cursor is malformed, belongs to another request context, or `limit` is outside its allowed range. |
| `404` | `NOT_FOUND` | The supplied `competitionId` is unavailable or does not expose Contributor Network items. |
| `422` | `RESOURCE_FIELD_INVALID` | A discriminator, scope, filter, sort, public code, unknown parameter, repeated parameter, or query-parameter combination is invalid. |

See [Errors](../../errors.md) for shared errors.
