---
title: "GitHub OAuth callback (sign-in or identity link)"
method: GET
path: "/oauth/github/callback"
tags: ["OAuth"]
---

# GitHub OAuth callback (sign-in or identity link)

`GET /oauth/github/callback`

## Request

- Base URL: `https://api.uptimemonitoring.com`
- URL: `https://api.uptimemonitoring.com/oauth/github/callback`
- Auth: none required

Handles the redirect from GitHub after authorization. In sign-in
mode, verifies the state parameter, exchanges the code for an
access token, upserts the account, and redirects to the frontend
with a one-time auth code.

Issue #390: in sign-in mode (never link mode), also fetches
GitHub's verified primary email address best-effort via
`GET /user/emails`. On a genuinely first sign-in for this GitHub
account, that address is consulted:

  - No address available, or nobody holds it yet: sign-in proceeds
    as before; an unclaimed address is saved onto the new user in
    the same transaction.
  - The address is already a verified email identity on an
    EXISTING user who has no GitHub identity of their own: the
    sign-in is merged into that user's existing account instead of
    creating a new one — the caller lands on the matched user's
    account, with the GitHub identity now attached to it. If that
    account is suspended, the callback redirects with
    `error=account_suspended`, the same as an email sign-in into a
    suspended account, and nothing is linked.
  - The address already belongs to a DIFFERENT user who already
    has their own GitHub identity: no merge; the sign-in creates an
    ordinary new user and account.

A merged or newly-adopted address enrolls the member in the
account's default-enabled weekly and monthly uptime reports and
becomes visible to the account's owner(s), the same as adding an
email through `POST /api/v1/me/identities/email/start`+`/verify`.

In identity-link mode (issue #325 — an `oauth_github_link` cookie
set by a prior `POST /oauth/github/link`), redeems the ticket
instead — every outcome, success or failure, redirects to
`{FRONTEND_URL}/settings?linked=github` or
`{FRONTEND_URL}/settings?link_error=<code>`, and sign-in is never
attempted. Mirrors `/oauth/google/callback`'s link-mode shape
exactly.

## Query parameters

- `code` string, required
- `state` string, required

## Other responses

- `302`: Redirect to frontend with auth code or error, or (link mode) to the settings page.
- `400`: Missing or invalid state/code parameter.

---

[API](https://skmtc.dev/uptimemonitoring/apis/uptimemonitoring-com-api.md) · [All operations](https://skmtc.dev/uptimemonitoring/apis/uptimemonitoring-com-api/llms.txt) · [OpenAPI document](https://skmtc.dev/uptimemonitoring/apis/uptimemonitoring-com-api/revisions/ddcb2a8bc70f?raw)
