---
title: "Link a GitHub identity with a personal access token"
method: POST
path: "/api/leaderboard/connect-github"
tags: ["leaderboard"]
---

# Link a GitHub identity with a personal access token

`POST /api/leaderboard/connect-github`

## Request

- Base URL: `https://www.immersivecommons.com`
- URL: `https://www.immersivecommons.com/api/leaderboard/connect-github`
- Auth: HTTP bearer

Clerk session or agt_ token with `github:link` (live tier re-checked). The PAT is verified against GitHub /user and then DISCARDED — only the resulting identity is stored, and the weekly leaderboard cron counts public commits with its own server-side token. Linking is the precondition for opting in at POST /api/leaderboard/optin.

## Request body

- ConnectGitHubRequest
  - `pat` string, required: A GitHub personal access token. Verified once against /user, then DISCARDED — it is never stored, logged, or echoed.

## Response `200`

Identity linked.

- ConnectGitHubResponse
  - `ok` boolean, required
  - `github` object, required: The identity that was stored. This, not the PAT, is what persists.
    - `login` string, required
    - `id` integer, required
    - `name` string
    - `avatarUrl` string
  - `via` 'clerk' | 'agent'

## Other responses

- `400`: Invalid JSON or missing pat.
- `401`: No auth.
- `403`: Scope/tier not authorized.
- `422`: GitHub rejected the PAT.
- `500`: Clerk update failed.
- `502`: GitHub was unreachable or returned a 5xx.

---

[API](https://skmtc.dev/immersivecommons/apis/immersive-commons-agent-rest-api.md) · [All operations](https://skmtc.dev/immersivecommons/apis/immersive-commons-agent-rest-api/llms.txt) · [OpenAPI document](https://skmtc.dev/immersivecommons/apis/immersive-commons-agent-rest-api/revisions/be67c1f67c27?raw)
