> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lmrp.uk/llms.txt
> Use this file to discover all available pages before exploring further.

# Complete Discord sign-in

> **Access:** Public. No session is needed.

Discord redirects the browser here. Argus verifies the state against the flow cookie, exchanges the code, creates or updates the account, replaces any existing session in this browser and issues a new one. State can be used once.

Signing in never grants a staff role.

Unknown query parameters are ignored.



## OpenAPI

````yaml /api-reference/openapi.json get /auth/discord/callback
openapi: 3.1.0
info:
  title: Argus API
  version: 0.1.0
  summary: The HTTP API behind the Argus web application.
  description: >-
    Argus is the operations platform for the UK London Mayfair ER:LC community.
    This document describes the API its own web application uses.


    **This is an internal application API.** It is not a stable public API:
    paths, fields and behaviour can change with any release, there is no
    versioning, and browser requests are tied to the application's own origin.
    Scoped service credentials exist for the community's own integrations.


    All paths are relative to `/api` on the deployment's origin. Responses are
    JSON, never cacheable, and carry an `X-Request-Id` header.
servers:
  - url: http://localhost:3000/api
    description: Local development
  - url: '{origin}/api'
    description: A deployment. `origin` is that deployment's `APP_URL`.
    variables:
      origin:
        default: https://argus.example.org
        description: The application's public origin, with no trailing slash.
security: []
tags:
  - name: Authentication
    description: >-
      Discord sign-in, Roblox account linking, the current user, and temporary
      Developer Access.
  - name: CAD Incidents
    description: >-
      Control's incidents: creation, editing, closure, and dispatching units to
      them.
  - name: CAD Units
    description: Control's view of operational units and their crew.
  - name: CAD Calls
    description: Incoming calls and how they become, or join, incidents.
  - name: CAD Events
    description: The append-only operational history.
  - name: MDT
    description: >-
      Self-service for the people crewing a unit: booking on and off, joining a
      unit, and changing its status.
  - name: Civilians
    description: 'The civilian portal: a member''s own characters, licences and vehicles.'
  - name: PNC Lookup
    description: >-
      Searching people and vehicles, full records, record history and official
      vehicle status.
  - name: PNC Licences
    description: Official changes to driving licences.
  - name: PNC Records
    description: Official records attached to people.
  - name: PNC Warrants
    description: Warrants and their lifecycle.
  - name: PNC Markers
    description: Markers and BOLOs on people and vehicles.
  - name: Staff
    description: Staff profiles and role membership.
  - name: Shifts
    description: Staff shifts.
  - name: Sessions
    description: Operational roleplay sessions.
  - name: Moderation
    description: Warnings, kicks and bans, with their delivery state.
  - name: Audit
    description: The append-only audit log.
  - name: Administration
    description: Accounts, roles and service credentials.
  - name: ERLC
    x-displayName: ER:LC
    description: Live data from the ER:LC private server.
paths:
  /auth/discord/callback:
    get:
      tags:
        - Authentication
      summary: Complete Discord sign-in
      description: >-
        **Access:** Public. No session is needed.


        Discord redirects the browser here. Argus verifies the state against the
        flow cookie, exchanges the code, creates or updates the account,
        replaces any existing session in this browser and issues a new one.
        State can be used once.


        Signing in never grants a staff role.


        Unknown query parameters are ignored.
      operationId: finishDiscordSignIn
      parameters:
        - name: state
          in: query
          required: true
          schema:
            type: string
            maxLength: 100
          description: The state Argus issued.
        - name: code
          in: query
          required: false
          schema:
            type: string
            minLength: 1
            maxLength: 2048
          description: Authorisation code from Discord.
        - name: error
          in: query
          required: false
          schema:
            type: string
          description: Set by Discord when the user cancels.
      responses:
        '302':
          description: >-
            Redirects to: The application root (`APP_URL/`). Sets the session
            cookie for seven days and clears the flow cookie.
          headers:
            Location:
              schema:
                type: string
                format: uri
              description: Where the browser is sent next.
            Set-Cookie:
              schema:
                type: string
              description: >-
                HttpOnly, SameSite=Lax cookies; Secure and `__Host-` prefixed in
                production.
            X-Request-Id:
              $ref: '#/components/headers/RequestId'
        '400':
          description: >-
            `INVALID_OAUTH_STATE`: state is missing, expired, already used, or
            from another browser.


            `OAUTH_DENIED`: the user cancelled or Discord refused.


            `INVALID_INPUT`: `code` is missing.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/RequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  code: INVALID_OAUTH_STATE
                  message: Authentication state is invalid or expired.
                requestId: 3f1c9d5e-7a42-4f0b-9c1e-8b6d2a4e5f70
        '403':
          description: '`ACCOUNT_DISABLED`: the Argus account is suspended or disabled.'
          headers:
            X-Request-Id:
              $ref: '#/components/headers/RequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  code: ACCOUNT_DISABLED
                  message: This account is not active.
                requestId: 3f1c9d5e-7a42-4f0b-9c1e-8b6d2a4e5f70
        '429':
          $ref: '#/components/responses/RateLimited'
        '502':
          description: >-
            `OAUTH_PROVIDER_ERROR`: Discord could not complete the exchange.


            `INVALID_PROVIDER_RESPONSE`: Discord returned an unusable token or
            profile.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/RequestId'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  code: OAUTH_PROVIDER_ERROR
                  message: >-
                    The identity provider could not complete authentication.
                    Please try signing in again.
                requestId: 3f1c9d5e-7a42-4f0b-9c1e-8b6d2a4e5f70
        '503':
          description: '`NOT_CONFIGURED`: the Discord client ID or secret is not set.'
          headers:
            X-Request-Id:
              $ref: '#/components/headers/RequestId'
            Retry-After:
              $ref: '#/components/headers/RetryAfter'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  code: NOT_CONFIGURED
                  message: ERLC_SERVER_KEY is not configured.
                requestId: 3f1c9d5e-7a42-4f0b-9c1e-8b6d2a4e5f70
        default:
          $ref: '#/components/responses/UnexpectedError'
      security: []
components:
  headers:
    RequestId:
      schema:
        type: string
        format: uuid
      description: Identifies this request in server logs.
    RetryAfter:
      schema:
        type: integer
        minimum: 1
      description: Seconds to wait before trying again.
  schemas:
    Error:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              description: Stable machine-readable code.
            message:
              type: string
            details:
              description: >-
                Present on some errors. Validation failures carry an array of
                `{path, message}`; ER:LC failures carry `{availability:
                "unavailable"}`.
          required:
            - code
            - message
        requestId:
          type: string
          format: uuid
          description: >-
            Also sent as the `X-Request-Id` header. Quote it when reporting a
            problem.
      required:
        - error
        - requestId
  responses:
    RateLimited:
      description: >-
        `RATE_LIMITED`: more than 180 reads or 60 writes in a minute for this
        caller.
      headers:
        X-Request-Id:
          $ref: '#/components/headers/RequestId'
        Retry-After:
          $ref: '#/components/headers/RetryAfter'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: RATE_LIMITED
              message: Too many requests.
            requestId: 3f1c9d5e-7a42-4f0b-9c1e-8b6d2a4e5f70
    UnexpectedError:
      description: >-
        Any other failure, in the same error envelope: `INTERNAL_ERROR` (500),
        `METHOD_NOT_ALLOWED` (405), `BODY_TOO_LARGE` (413, over 16 KiB) or
        `UNSUPPORTED_MEDIA_TYPE` (415, body not sent as `application/json`).
      headers:
        X-Request-Id:
          $ref: '#/components/headers/RequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: INTERNAL_ERROR
              message: The request could not be completed.
            requestId: 3f1c9d5e-7a42-4f0b-9c1e-8b6d2a4e5f70

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.