{
  "openapi": "3.1.0",
  "info": {
    "title": "RSX ID",
    "version": "v1",
    "description": "Account and identity service — registration, login, sessions, and the platform's JWT issuer (JWKS)."
  },
  "servers": [
    {
      "url": "https://api.rsx.group"
    }
  ],
  "components": {
    "securitySchemes": {
      "consumerApiKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "A platform API key, sent as `Authorization: Bearer rsx_live_...`. Keys are issued, scoped, rotated, and revoked through the platform service (/platform/v1/keys/*) — revocation takes effect platform-wide without a redeploy here. The `id:*` read scopes on this surface are not developer-self-grantable: only an admin-issued key can carry them."
      }
    },
    "schemas": {
      "Account": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "example": "0198f2b1-6c2a-7c9e-9d3a-1e2f3a4b5c6d"
          },
          "email": {
            "type": "string",
            "maxLength": 254,
            "format": "email",
            "description": "Login email. Stored lowercased.",
            "example": "ada@example.com"
          },
          "emailVerified": {
            "type": "boolean",
            "example": false
          },
          "username": {
            "type": "string",
            "pattern": "^[a-zA-Z][a-zA-Z0-9_]{2,29}$",
            "description": "Public @handle. Case-insensitive.",
            "example": "ada_lovelace"
          },
          "displayName": {
            "type": [
              "string",
              "null"
            ],
            "minLength": 1,
            "maxLength": 80,
            "example": "Ada Lovelace"
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "suspended",
              "terminated"
            ],
            "example": "active"
          },
          "statusReason": {
            "type": [
              "string",
              "null"
            ],
            "description": "Set when an admin suspends/terminates the account.",
            "example": null
          },
          "type": {
            "type": "string",
            "enum": [
              "user",
              "developer"
            ],
            "example": "user"
          },
          "staffRole": {
            "type": "string",
            "enum": [
              "none",
              "staff",
              "admin"
            ],
            "example": "none"
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "string",
              "pattern": "^[a-z][a-z0-9-]*(:[a-z0-9-*]+)*$",
              "example": "id:accounts:manage"
            },
            "example": []
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-07-27T12:00:00Z"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-07-27T12:00:00Z"
          }
        },
        "required": [
          "id",
          "email",
          "emailVerified",
          "username",
          "displayName",
          "status",
          "statusReason",
          "type",
          "staffRole",
          "scopes",
          "createdAt",
          "updatedAt"
        ]
      },
      "Credentials": {
        "type": "object",
        "properties": {
          "tokenType": {
            "type": "string",
            "enum": [
              "Bearer"
            ],
            "example": "Bearer"
          },
          "accessToken": {
            "type": "string",
            "description": "Short-lived ES256 JWT. Verify it via the JWKS endpoint.",
            "example": "eyJhbGciOiJFUzI1NiIsImtpZCI6Ii4uLiJ9..."
          },
          "expiresIn": {
            "type": "integer",
            "description": "Access-token TTL, seconds.",
            "example": 900
          },
          "refreshToken": {
            "type": "string",
            "description": "Opaque, long-lived, rotated on every use. Stored hashed server-side.",
            "example": "rsx_rt_9f8e7d..."
          },
          "refreshExpiresIn": {
            "type": "integer",
            "example": 2592000
          },
          "account": {
            "$ref": "#/components/schemas/Account"
          }
        },
        "required": [
          "tokenType",
          "accessToken",
          "expiresIn",
          "refreshToken",
          "refreshExpiresIn",
          "account"
        ]
      },
      "Registered": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Credentials"
          },
          {
            "type": "object",
            "properties": {
              "emailVerificationToken": {
                "type": "string",
                "description": "Dev-only: present when DEV_RETURN_TOKENS=1 (in production this is emailed)."
              }
            }
          }
        ]
      },
      "Register": {
        "type": "object",
        "properties": {
          "email": {
            "type": "string",
            "maxLength": 254,
            "format": "email",
            "description": "Login email. Stored lowercased.",
            "example": "ada@example.com"
          },
          "username": {
            "type": "string",
            "pattern": "^[a-zA-Z][a-zA-Z0-9_]{2,29}$",
            "description": "Public @handle. Case-insensitive.",
            "example": "ada_lovelace"
          },
          "password": {
            "type": "string",
            "minLength": 10,
            "maxLength": 256,
            "description": "Never stored or returned.",
            "example": "correct horse battery staple"
          },
          "displayName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 80,
            "example": "Ada Lovelace"
          }
        },
        "required": [
          "email",
          "username",
          "password"
        ]
      },
      "Login": {
        "type": "object",
        "properties": {
          "identifier": {
            "type": "string",
            "minLength": 1,
            "description": "Email or @handle (with or without @).",
            "example": "ada@example.com"
          },
          "password": {
            "type": "string",
            "minLength": 1
          }
        },
        "required": [
          "identifier",
          "password"
        ]
      },
      "Refresh": {
        "type": "object",
        "properties": {
          "refreshToken": {
            "type": "string",
            "minLength": 1
          }
        },
        "required": [
          "refreshToken"
        ]
      },
      "Accepted": {
        "type": "object",
        "properties": {
          "accepted": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "token": {
            "type": "string",
            "description": "Dev-only (DEV_RETURN_TOKENS=1)."
          }
        },
        "required": [
          "accepted"
        ]
      },
      "RevokeSession": {
        "type": "object",
        "properties": {
          "refreshToken": {
            "type": "string",
            "minLength": 1
          }
        },
        "required": [
          "refreshToken"
        ]
      },
      "VerifyEmail": {
        "type": "object",
        "properties": {
          "token": {
            "type": "string",
            "minLength": 1
          }
        },
        "required": [
          "token"
        ]
      },
      "RequestVerification": {
        "type": "object",
        "properties": {
          "email": {
            "type": "string",
            "maxLength": 254,
            "format": "email",
            "description": "Login email. Stored lowercased.",
            "example": "ada@example.com"
          }
        },
        "required": [
          "email"
        ]
      },
      "RequestPasswordReset": {
        "type": "object",
        "properties": {
          "email": {
            "type": "string",
            "maxLength": 254,
            "format": "email",
            "description": "Login email. Stored lowercased.",
            "example": "ada@example.com"
          }
        },
        "required": [
          "email"
        ]
      },
      "ResetPassword": {
        "type": "object",
        "properties": {
          "token": {
            "type": "string",
            "minLength": 1
          },
          "password": {
            "type": "string",
            "minLength": 10,
            "maxLength": 256,
            "description": "Never stored or returned.",
            "example": "correct horse battery staple"
          }
        },
        "required": [
          "token",
          "password"
        ]
      },
      "UpdateAccount": {
        "type": "object",
        "properties": {
          "displayName": {
            "type": [
              "string",
              "null"
            ],
            "minLength": 1,
            "maxLength": 80,
            "example": "Ada Lovelace"
          },
          "username": {
            "type": "string",
            "pattern": "^[a-zA-Z][a-zA-Z0-9_]{2,29}$",
            "description": "Public @handle. Case-insensitive.",
            "example": "ada_lovelace"
          },
          "email": {
            "type": "string",
            "maxLength": 254,
            "format": "email",
            "description": "Login email. Stored lowercased.",
            "example": "ada@example.com"
          }
        }
      },
      "ChangePassword": {
        "type": "object",
        "properties": {
          "currentPassword": {
            "type": "string",
            "minLength": 1
          },
          "newPassword": {
            "type": "string",
            "minLength": 10,
            "maxLength": 256,
            "description": "Never stored or returned.",
            "example": "correct horse battery staple"
          }
        },
        "required": [
          "currentPassword",
          "newPassword"
        ]
      },
      "BecomeDeveloper": {
        "type": "object",
        "properties": {
          "acceptTerms": {
            "type": "boolean",
            "enum": [
              true
            ],
            "description": "Must be true — explicit consent to the RSX Developer Terms."
          }
        },
        "required": [
          "acceptTerms"
        ]
      },
      "SessionInfo": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "userAgent": {
            "type": [
              "string",
              "null"
            ],
            "example": "Mozilla/5.0 ..."
          },
          "ip": {
            "type": [
              "string",
              "null"
            ],
            "example": "203.0.113.7"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "lastUsedAt": {
            "type": "string",
            "format": "date-time"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time"
          },
          "current": {
            "type": "boolean",
            "description": "True for the session making this request."
          }
        },
        "required": [
          "id",
          "userAgent",
          "ip",
          "createdAt",
          "lastUsedAt",
          "expiresAt",
          "current"
        ]
      },
      "SuspendAccount": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "reason": {
            "type": "string",
            "maxLength": 500,
            "example": "Spam reports under review."
          }
        },
        "required": [
          "id"
        ]
      },
      "ReinstateAccount": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          }
        },
        "required": [
          "id"
        ]
      },
      "TerminateAccount": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "reason": {
            "type": "string",
            "maxLength": 500,
            "example": "Repeated ToS violations."
          }
        },
        "required": [
          "id"
        ]
      },
      "AdminUpdateAccount": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "email": {
            "type": "string",
            "maxLength": 254,
            "format": "email",
            "description": "Login email. Stored lowercased.",
            "example": "ada@example.com"
          },
          "username": {
            "type": "string",
            "pattern": "^[a-zA-Z][a-zA-Z0-9_]{2,29}$",
            "description": "Public @handle. Case-insensitive.",
            "example": "ada_lovelace"
          },
          "displayName": {
            "type": [
              "string",
              "null"
            ],
            "minLength": 1,
            "maxLength": 80,
            "example": "Ada Lovelace"
          },
          "emailVerified": {
            "type": "boolean"
          },
          "force": {
            "type": "boolean",
            "description": "Bypass another user's handle reservation when reassigning a handle."
          }
        },
        "required": [
          "id"
        ]
      },
      "AdminResetResult": {
        "type": "object",
        "properties": {
          "account": {
            "$ref": "#/components/schemas/Account"
          },
          "resetToken": {
            "type": "string",
            "description": "One-time password-reset token. Hand it to the account owner; it is not stored in the clear."
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "account",
          "resetToken",
          "expiresAt"
        ]
      },
      "AdminResetPassword": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          }
        },
        "required": [
          "id"
        ]
      },
      "AdminCreateAccount": {
        "type": "object",
        "properties": {
          "email": {
            "type": "string",
            "maxLength": 254,
            "format": "email",
            "description": "Login email. Stored lowercased.",
            "example": "ada@example.com"
          },
          "username": {
            "type": "string",
            "pattern": "^[a-zA-Z][a-zA-Z0-9_]{2,29}$",
            "description": "Public @handle. Case-insensitive.",
            "example": "ada_lovelace"
          },
          "displayName": {
            "type": [
              "string",
              "null"
            ],
            "minLength": 1,
            "maxLength": 80,
            "example": "Ada Lovelace"
          },
          "emailVerified": {
            "type": "boolean",
            "example": false
          },
          "type": {
            "type": "string",
            "enum": [
              "user",
              "developer"
            ],
            "example": "user"
          },
          "staffRole": {
            "type": "string",
            "enum": [
              "none",
              "staff",
              "admin"
            ],
            "example": "none"
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "string",
              "pattern": "^[a-z][a-z0-9-]*(:[a-z0-9-*]+)*$",
              "example": "id:accounts:manage"
            }
          }
        },
        "required": [
          "email",
          "username"
        ]
      },
      "AdminRevokeSession": {
        "type": "object",
        "properties": {
          "sessionId": {
            "type": "string",
            "format": "uuid"
          }
        },
        "required": [
          "sessionId"
        ]
      },
      "SetRole": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "staffRole": {
            "type": "string",
            "enum": [
              "none",
              "staff",
              "admin"
            ],
            "example": "none"
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "string",
              "pattern": "^[a-z][a-z0-9-]*(:[a-z0-9-*]+)*$",
              "example": "id:accounts:manage"
            }
          },
          "type": {
            "type": "string",
            "enum": [
              "user",
              "developer"
            ],
            "example": "user"
          }
        },
        "required": [
          "id"
        ]
      },
      "AccountAuditRecord": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "actor": {
            "type": "string",
            "description": "Admin email, 'user', or 'system'.",
            "example": "admin@rsx.group"
          },
          "action": {
            "type": "string",
            "enum": [
              "register",
              "email_verified",
              "handle_changed",
              "email_changed",
              "password_changed",
              "password_reset",
              "suspended",
              "reinstated",
              "terminated",
              "admin_updated",
              "developer_enabled",
              "role_changed",
              "link_added",
              "link_removed",
              "admin_created",
              "session_revoked",
              "oidc_client_created",
              "oidc_client_revoked",
              "oidc_client_trust_changed",
              "oidc_client_updated",
              "oidc_client_secret_rotated",
              "oidc_client_restored"
            ]
          },
          "targetType": {
            "type": "string",
            "enum": [
              "account",
              "oidc_client"
            ]
          },
          "targetId": {
            "type": "string",
            "example": "0198f0c2-1b3a-7c4d-9e5f-6a7b8c9d0e1f"
          },
          "at": {
            "type": "string",
            "format": "date-time"
          },
          "detail": {
            "type": [
              "string",
              "null"
            ],
            "example": "old=ada new=ada_l"
          }
        },
        "required": [
          "id",
          "actor",
          "action",
          "targetType",
          "targetId",
          "at",
          "detail"
        ]
      },
      "OidcClient": {
        "type": "object",
        "properties": {
          "clientId": {
            "type": "string",
            "example": "rsx_client_a1b2c3d4"
          },
          "name": {
            "type": "string",
            "example": "Cloudflare Access"
          },
          "redirectUris": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uri"
            }
          },
          "trusted": {
            "type": "boolean",
            "description": "First-party: skips the consent screen and receives internal group/role claims."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "revoked": {
            "type": "boolean"
          }
        },
        "required": [
          "clientId",
          "name",
          "redirectUris",
          "trusted",
          "createdAt",
          "revoked"
        ]
      },
      "CreatedOidcClient": {
        "allOf": [
          {
            "$ref": "#/components/schemas/OidcClient"
          },
          {
            "type": "object",
            "properties": {
              "clientSecret": {
                "type": "string",
                "description": "Shown once, at creation — not retrievable."
              }
            },
            "required": [
              "clientSecret"
            ]
          }
        ]
      },
      "CreateOidcClient": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "redirectUris": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uri"
            },
            "minItems": 1
          },
          "trusted": {
            "type": "boolean"
          }
        },
        "required": [
          "name",
          "redirectUris"
        ]
      },
      "RevokeOidcClient": {
        "type": "object",
        "properties": {
          "clientId": {
            "type": "string"
          }
        },
        "required": [
          "clientId"
        ]
      },
      "UpdateOidcClient": {
        "type": "object",
        "properties": {
          "clientId": {
            "type": "string"
          },
          "trusted": {
            "type": "boolean"
          },
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "redirectUris": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uri"
            },
            "minItems": 1
          }
        },
        "required": [
          "clientId"
        ]
      },
      "RotatedOidcSecret": {
        "type": "object",
        "properties": {
          "clientId": {
            "type": "string"
          },
          "clientSecret": {
            "type": "string",
            "description": "Shown once — the store keeps only a hash."
          }
        },
        "required": [
          "clientId",
          "clientSecret"
        ]
      },
      "RotateOidcSecret": {
        "type": "object",
        "properties": {
          "clientId": {
            "type": "string"
          }
        },
        "required": [
          "clientId"
        ]
      },
      "RestoreOidcClient": {
        "type": "object",
        "properties": {
          "clientId": {
            "type": "string"
          }
        },
        "required": [
          "clientId"
        ]
      },
      "OidcAuthorizeResult": {
        "type": "object",
        "properties": {
          "redirectTo": {
            "type": "string"
          },
          "consentRequired": {
            "type": "boolean"
          },
          "client": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string"
              },
              "scopes": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            },
            "required": [
              "name",
              "scopes"
            ]
          }
        }
      },
      "OidcAuthorizeRequest": {
        "type": "object",
        "properties": {
          "clientId": {
            "type": "string"
          },
          "redirectUri": {
            "type": "string",
            "format": "uri"
          },
          "scope": {
            "type": "string",
            "example": "openid email profile"
          },
          "claims": {
            "type": "string",
            "example": "email preferred_username groups"
          },
          "state": {
            "type": "string"
          },
          "nonce": {
            "type": "string"
          },
          "codeChallenge": {
            "type": "string"
          },
          "codeChallengeMethod": {
            "type": "string",
            "enum": [
              "S256"
            ]
          },
          "responseType": {
            "type": "string"
          },
          "consent": {
            "type": "boolean"
          }
        },
        "required": [
          "clientId",
          "redirectUri",
          "scope"
        ]
      },
      "AccountLink": {
        "type": "object",
        "properties": {
          "provider": {
            "type": "string",
            "enum": [
              "github",
              "discord",
              "roblox"
            ],
            "example": "github"
          },
          "externalId": {
            "type": "string",
            "description": "The provider's stable user id.",
            "example": "1024025"
          },
          "externalHandle": {
            "type": [
              "string",
              "null"
            ],
            "description": "Login / username, for display.",
            "example": "octocat"
          },
          "avatarUrl": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri",
            "example": "https://avatars.githubusercontent.com/u/1024025"
          },
          "verified": {
            "type": "boolean",
            "description": "True when ownership was proven via the provider's OAuth flow."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "provider",
          "externalId",
          "externalHandle",
          "avatarUrl",
          "verified",
          "createdAt"
        ]
      },
      "StartLinkResult": {
        "type": "object",
        "properties": {
          "authorizeUrl": {
            "type": "string",
            "format": "uri",
            "description": "The provider's authorization URL. The browser is redirected here to grant access."
          }
        },
        "required": [
          "authorizeUrl"
        ]
      },
      "StartLink": {
        "type": "object",
        "properties": {
          "provider": {
            "type": "string",
            "enum": [
              "github",
              "discord"
            ],
            "example": "github"
          }
        },
        "required": [
          "provider"
        ]
      },
      "LinkCallback": {
        "type": "object",
        "properties": {
          "provider": {
            "type": "string",
            "enum": [
              "github",
              "discord"
            ],
            "example": "github"
          },
          "code": {
            "type": "string",
            "minLength": 1
          },
          "state": {
            "type": "string",
            "minLength": 1
          }
        },
        "required": [
          "provider",
          "code",
          "state"
        ]
      },
      "RobloxLink": {
        "type": "object",
        "properties": {
          "username": {
            "type": "string",
            "minLength": 3,
            "maxLength": 20,
            "pattern": "^[A-Za-z0-9_]+$",
            "example": "builderman"
          }
        },
        "required": [
          "username"
        ]
      },
      "Unlink": {
        "type": "object",
        "properties": {
          "provider": {
            "type": "string",
            "enum": [
              "github",
              "discord",
              "roblox"
            ],
            "example": "github"
          }
        },
        "required": [
          "provider"
        ]
      },
      "AccountIdentity": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "example": "0198f2b1-6c2a-7c9e-9d3a-1e2f3a4b5c6d"
          },
          "username": {
            "type": "string",
            "pattern": "^[a-zA-Z][a-zA-Z0-9_]{2,29}$",
            "description": "Public @handle. Case-insensitive.",
            "example": "ada_lovelace"
          },
          "displayName": {
            "type": [
              "string",
              "null"
            ],
            "minLength": 1,
            "maxLength": 80,
            "example": "Ada Lovelace"
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "suspended",
              "terminated"
            ],
            "example": "active"
          },
          "type": {
            "type": "string",
            "enum": [
              "user",
              "developer"
            ],
            "example": "user"
          }
        },
        "required": [
          "id",
          "username",
          "displayName",
          "status",
          "type"
        ]
      },
      "AccountAuthorization": {
        "type": "object",
        "properties": {
          "staffRole": {
            "type": "string",
            "enum": [
              "none",
              "staff",
              "admin"
            ],
            "example": "none"
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "string",
              "pattern": "^[a-z][a-z0-9-]*(:[a-z0-9-*]+)*$",
              "example": "id:accounts:manage"
            },
            "description": "Scopes as assigned. Not status-aware — see effectiveScopes.",
            "example": []
          },
          "active": {
            "type": "boolean",
            "description": "True only while status is 'active'. False for suspended and terminated.",
            "example": true
          },
          "admin": {
            "type": "boolean",
            "description": "Active RSX administrator."
          },
          "staff": {
            "type": "boolean",
            "description": "Active RSX staff. Downward-closed — an admin is also staff."
          },
          "effectiveScopes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Scopes actually in force: ['*'] for an active admin, the assigned scopes for active staff, empty otherwise.",
            "example": []
          }
        },
        "required": [
          "staffRole",
          "scopes",
          "active",
          "admin",
          "staff",
          "effectiveScopes"
        ]
      },
      "ResolvedIdentity": {
        "type": "object",
        "properties": {
          "account": {
            "$ref": "#/components/schemas/AccountIdentity"
          },
          "link": {
            "$ref": "#/components/schemas/AccountLink"
          },
          "authorization": {
            "$ref": "#/components/schemas/AccountAuthorization"
          }
        },
        "required": [
          "account",
          "link",
          "authorization"
        ]
      },
      "Problem": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "example": "https://docs.rsx.group/errors/identity-not-linked"
          },
          "title": {
            "type": "string",
            "example": "Identity not linked"
          },
          "status": {
            "type": "integer",
            "example": 404
          },
          "detail": {
            "type": "string"
          },
          "instance": {
            "type": "string",
            "example": "/id/v1/identity/resolve"
          },
          "requestId": {
            "type": "string"
          }
        },
        "required": [
          "type",
          "title",
          "status"
        ]
      },
      "LinkOwner": {
        "type": "object",
        "properties": {
          "accountId": {
            "type": "string",
            "format": "uuid",
            "example": "0198f2b1-6c2a-7c9e-9d3a-1e2f3a4b5c6d"
          },
          "link": {
            "$ref": "#/components/schemas/AccountLink"
          }
        },
        "required": [
          "accountId",
          "link"
        ]
      },
      "Jwks": {
        "type": "object",
        "properties": {
          "keys": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "kty": {
                  "type": "string",
                  "example": "EC"
                },
                "crv": {
                  "type": "string",
                  "example": "P-256"
                },
                "x": {
                  "type": "string"
                },
                "y": {
                  "type": "string"
                },
                "kid": {
                  "type": "string"
                },
                "use": {
                  "type": "string",
                  "example": "sig"
                },
                "alg": {
                  "type": "string",
                  "example": "ES256"
                }
              },
              "required": [
                "kty",
                "crv",
                "x",
                "y",
                "kid",
                "use",
                "alg"
              ]
            }
          }
        },
        "required": [
          "keys"
        ]
      }
    },
    "parameters": {}
  },
  "paths": {
    "/id/v1/accounts/register": {
      "post": {
        "operationId": "register",
        "summary": "Create an account",
        "tags": [
          "accounts"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Register"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Account created; access + refresh tokens issued",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Registered"
                }
              }
            }
          }
        }
      }
    },
    "/id/v1/sessions/create": {
      "post": {
        "operationId": "login",
        "summary": "Log in (create a session)",
        "tags": [
          "sessions"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Login"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Authenticated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Credentials"
                }
              }
            }
          }
        }
      }
    },
    "/id/v1/sessions/refresh": {
      "post": {
        "operationId": "refreshSession",
        "summary": "Exchange a refresh token for a new session",
        "tags": [
          "sessions"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Refresh"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Rotated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Credentials"
                }
              }
            }
          }
        }
      }
    },
    "/id/v1/sessions/revoke": {
      "post": {
        "operationId": "revokeSession",
        "summary": "Log out (revoke a refresh token)",
        "tags": [
          "sessions"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RevokeSession"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Revoked (idempotent)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          }
        }
      }
    },
    "/id/v1/accounts/verify-email": {
      "post": {
        "operationId": "verifyEmail",
        "summary": "Confirm an email address",
        "tags": [
          "accounts"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VerifyEmail"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Verified",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Account"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/id/v1/accounts/request-verification": {
      "post": {
        "operationId": "requestVerification",
        "summary": "Request a new email-verification token",
        "tags": [
          "accounts"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RequestVerification"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Accepted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          }
        }
      }
    },
    "/id/v1/accounts/request-password-reset": {
      "post": {
        "operationId": "requestPasswordReset",
        "summary": "Request a password-reset token",
        "tags": [
          "accounts"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RequestPasswordReset"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Accepted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          }
        }
      }
    },
    "/id/v1/accounts/reset-password": {
      "post": {
        "operationId": "resetPassword",
        "summary": "Set a new password with a reset token",
        "tags": [
          "accounts"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ResetPassword"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Password reset; all sessions revoked",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          }
        }
      }
    },
    "/id/v1/accounts/me": {
      "get": {
        "operationId": "getMe",
        "summary": "Fetch the authenticated account",
        "tags": [
          "accounts"
        ],
        "responses": {
          "200": {
            "description": "Account",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Account"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/id/v1/accounts/update": {
      "post": {
        "operationId": "updateMe",
        "summary": "Update the authenticated account",
        "tags": [
          "accounts"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateAccount"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Account"
                    },
                    "emailVerificationToken": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/id/v1/accounts/change-password": {
      "post": {
        "operationId": "changePassword",
        "summary": "Change the authenticated account's password",
        "tags": [
          "accounts"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ChangePassword"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Changed; other sessions revoked",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          }
        }
      }
    },
    "/id/v1/accounts/become-developer": {
      "post": {
        "operationId": "becomeDeveloper",
        "summary": "Opt in to a developer account",
        "tags": [
          "accounts"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BecomeDeveloper"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Now a developer account",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Account"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/id/v1/sessions/list": {
      "get": {
        "operationId": "listSessions",
        "summary": "List active sessions",
        "tags": [
          "sessions"
        ],
        "responses": {
          "200": {
            "description": "Sessions",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/SessionInfo"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/id/v1/sessions/revoke-others": {
      "post": {
        "operationId": "revokeOtherSessions",
        "summary": "Revoke every session except the current one",
        "tags": [
          "sessions"
        ],
        "responses": {
          "200": {
            "description": "Revoked",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          }
        }
      }
    },
    "/id/v1/admin/accounts/list": {
      "get": {
        "operationId": "adminListAccounts",
        "summary": "List accounts (admin)",
        "tags": [
          "admin"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": ""
            },
            "required": false,
            "name": "cursor",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50,
              "example": 50
            },
            "required": false,
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Email or handle prefix search.",
              "example": "ada"
            },
            "required": false,
            "name": "q",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Accounts",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Account"
                      }
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "cursor": {
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "cursor"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/id/v1/admin/accounts/get": {
      "get": {
        "operationId": "adminGetAccount",
        "summary": "Fetch one account (admin)",
        "tags": [
          "admin"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true,
            "name": "id",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Account",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Account"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/id/v1/admin/accounts/suspend": {
      "post": {
        "operationId": "adminSuspendAccount",
        "summary": "Suspend an account (temporary block)",
        "tags": [
          "admin"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SuspendAccount"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Suspended",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Account"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/id/v1/admin/accounts/reinstate": {
      "post": {
        "operationId": "adminReinstateAccount",
        "summary": "Reinstate a suspended/terminated account",
        "tags": [
          "admin"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReinstateAccount"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Reinstated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Account"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/id/v1/admin/accounts/terminate": {
      "post": {
        "operationId": "adminTerminateAccount",
        "summary": "Terminate an account (permanent block)",
        "tags": [
          "admin"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TerminateAccount"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Terminated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Account"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/id/v1/admin/accounts/update": {
      "post": {
        "operationId": "adminUpdateAccount",
        "summary": "Edit account details (admin)",
        "tags": [
          "admin"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AdminUpdateAccount"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Account"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/id/v1/admin/accounts/reset-password": {
      "post": {
        "operationId": "adminResetPassword",
        "summary": "Issue a password-reset token (admin recovery)",
        "tags": [
          "admin"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AdminResetPassword"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Reset token issued",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/AdminResetResult"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/id/v1/admin/accounts/create": {
      "post": {
        "operationId": "adminCreateAccount",
        "summary": "Create an account (admin)",
        "tags": [
          "admin"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AdminCreateAccount"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Account created; the reset token is shown once for out-of-band handoff",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/AdminResetResult"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/id/v1/admin/sessions/list": {
      "get": {
        "operationId": "adminListSessions",
        "summary": "List an account's active sessions (admin)",
        "tags": [
          "admin"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "required": true,
            "name": "accountId",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Active sessions, most recently used first",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/SessionInfo"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/id/v1/admin/sessions/revoke": {
      "post": {
        "operationId": "adminRevokeSession",
        "summary": "Revoke one session (admin)",
        "tags": [
          "admin"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AdminRevokeSession"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Revoked (idempotent)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          }
        }
      }
    },
    "/id/v1/admin/accounts/set-role": {
      "post": {
        "operationId": "adminSetRole",
        "summary": "Assign an account's internal role / scopes (admin)",
        "tags": [
          "admin"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetRole"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Role updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Account"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/id/v1/admin/audit/list": {
      "get": {
        "operationId": "adminListAudit",
        "summary": "List the account audit trail (admin)",
        "tags": [
          "admin"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": ""
            },
            "required": false,
            "name": "cursor",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50,
              "example": 50
            },
            "required": false,
            "name": "limit",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Audit records, newest first",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/AccountAuditRecord"
                      }
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "cursor": {
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "cursor"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/id/v1/admin/oidc/clients": {
      "post": {
        "operationId": "createOidcClient",
        "summary": "Register an OIDC client (admin)",
        "tags": [
          "oidc"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateOidcClient"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Client created — secret shown once",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/CreatedOidcClient"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listOidcClients",
        "summary": "List OIDC clients (admin)",
        "tags": [
          "oidc"
        ],
        "responses": {
          "200": {
            "description": "Clients",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/OidcClient"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/id/v1/admin/oidc/clients/revoke": {
      "post": {
        "operationId": "revokeOidcClient",
        "summary": "Revoke an OIDC client (admin)",
        "tags": [
          "oidc"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RevokeOidcClient"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Revoked",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "revoked": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "revoked"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/id/v1/admin/oidc/clients/update": {
      "post": {
        "operationId": "updateOidcClient",
        "summary": "Edit an OIDC client's name, redirect URIs, or trusted flag (admin)",
        "tags": [
          "oidc"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateOidcClient"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/OidcClient"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/id/v1/admin/oidc/clients/rotate-secret": {
      "post": {
        "operationId": "rotateOidcClientSecret",
        "summary": "Issue a new client secret (admin)",
        "tags": [
          "oidc"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RotateOidcSecret"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "New secret — shown exactly once",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/RotatedOidcSecret"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/id/v1/admin/oidc/clients/restore": {
      "post": {
        "operationId": "restoreOidcClient",
        "summary": "Un-revoke an OIDC client (admin)",
        "tags": [
          "oidc"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RestoreOidcClient"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Restored",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/OidcClient"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/id/v1/oidc/authorize": {
      "post": {
        "operationId": "oidcAuthorize",
        "summary": "Issue an OIDC authorization code",
        "tags": [
          "oidc"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OidcAuthorizeRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Redirect target, or consent required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OidcAuthorizeResult"
                }
              }
            }
          }
        }
      }
    },
    "/id/v1/accounts/links": {
      "get": {
        "operationId": "listAccountLinks",
        "summary": "List the authenticated account's connected accounts",
        "tags": [
          "accounts"
        ],
        "responses": {
          "200": {
            "description": "Connected accounts",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/AccountLink"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/id/v1/accounts/links/start": {
      "post": {
        "operationId": "startAccountLink",
        "summary": "Begin an OAuth account link (GitHub/Discord)",
        "tags": [
          "accounts"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/StartLink"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Provider authorize URL",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StartLinkResult"
                }
              }
            }
          }
        }
      }
    },
    "/id/v1/accounts/links/callback": {
      "post": {
        "operationId": "completeAccountLink",
        "summary": "Complete an OAuth account link (internal)",
        "tags": [
          "accounts"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LinkCallback"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Linked",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/AccountLink"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/id/v1/accounts/links/roblox": {
      "post": {
        "operationId": "linkRoblox",
        "summary": "Link a Roblox username (cosmetic, unverified)",
        "tags": [
          "accounts"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RobloxLink"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Linked",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/AccountLink"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/id/v1/accounts/links/unlink": {
      "post": {
        "operationId": "unlinkAccount",
        "summary": "Remove a connected account",
        "tags": [
          "accounts"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Unlink"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Removed (idempotent)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Accepted"
                }
              }
            }
          }
        }
      }
    },
    "/id/v1/identity/resolve": {
      "get": {
        "operationId": "resolveIdentity",
        "summary": "Resolve an external identity to an RSX ID account",
        "description": "Requires an API key with the `id:identity:resolve` scope.\n\nAnswers the whole authorization question in one call: who this external identity is on RSX, the link that proves it, and what the account may currently do. Only OAuth-verified providers resolve — a self-asserted handle is not proof of ownership.\n\nA valid identifier that no account has connected is a 404 `identity-not-linked`, distinct from an unknown account and from a malformed request, so an unlinked user and a broken call never look alike. A linked but suspended or terminated account still resolves (200) with its status and with `authorization.active: false` — the consumer decides what to do about it.\n\nCacheable for 15 seconds, privately. Do not hold the result longer: it carries authority.",
        "tags": [
          "identity"
        ],
        "security": [
          {
            "consumerApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "enum": [
                "github",
                "discord"
              ],
              "example": "github"
            },
            "required": true,
            "name": "provider",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9._-]{1,64}$",
              "description": "The provider's stable user id.",
              "example": "216773161785950208"
            },
            "required": true,
            "name": "externalId",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "The identity is linked; account, link, and authorization returned",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ResolvedIdentity"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing, unrecognised, or revoked API key",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "The key is valid but lacks the scope this route requires",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No RSX ID has this external identity linked and verified",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/id/v1/identity/get": {
      "get": {
        "operationId": "getIdentity",
        "summary": "Fetch an account's identity by RSX account id",
        "description": "Requires an API key with the `id:identity:get` scope.\n\nThe minimal identity view for an account a consumer already holds the id of. Deliberately smaller than the account-management representation: no email, no verification state, no timestamps. Takes an exact account id only — there is no listing or search on this surface, so it cannot be walked to enumerate accounts.\n\nCacheable for 60 seconds, privately.",
        "tags": [
          "identity"
        ],
        "security": [
          {
            "consumerApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "0198f2b1-6c2a-7c9e-9d3a-1e2f3a4b5c6d"
            },
            "required": true,
            "name": "accountId",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Account identity",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/AccountIdentity"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing, unrecognised, or revoked API key",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "The key is valid but lacks the scope this route requires",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No account with that id",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/id/v1/authorization/get": {
      "get": {
        "operationId": "getAuthorization",
        "summary": "Fetch an account's role and scopes",
        "description": "Requires an API key with the `id:authorization:get` scope.\n\nRSX ID's authoritative answer to what an account may do — the existing `staffRole` + `scopes` model, not a consumer-specific one. `staffRole` and `scopes` are the raw assignment; `active`, `admin`, `staff`, and `effectiveScopes` are what is in force right now and all account for suspension and termination, so the simple check is also the safe one.\n\nCacheable for 15 seconds, privately. Role and scope changes are visible on the next read — there is no invalidation callback, so this window is the staleness bound a consumer inherits.",
        "tags": [
          "identity"
        ],
        "security": [
          {
            "consumerApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "0198f2b1-6c2a-7c9e-9d3a-1e2f3a4b5c6d"
            },
            "required": true,
            "name": "accountId",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Assigned role/scopes plus what is currently in force",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/AccountAuthorization"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing, unrecognised, or revoked API key",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "The key is valid but lacks the scope this route requires",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No account with that id",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/id/v1/links/lookup": {
      "get": {
        "operationId": "lookupAccountLink",
        "summary": "Find which RSX ID owns an external identity",
        "description": "Requires an API key with the `id:links:lookup` scope.\n\nThe narrow half of resolution: the RSX account id behind a verified external identity, and the link itself. Nothing about the account's identity or authority is returned, so a consumer that only needs the id-to-id mapping can hold a credential that can never read a role.\n\nSame `identity-not-linked` semantics as `resolveIdentity`. Cacheable for 60 seconds, privately; a link removed or re-pointed at another account is visible on the next read.",
        "tags": [
          "identity"
        ],
        "security": [
          {
            "consumerApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "enum": [
                "github",
                "discord"
              ],
              "example": "github"
            },
            "required": true,
            "name": "provider",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9._-]{1,64}$",
              "description": "The provider's stable user id.",
              "example": "216773161785950208"
            },
            "required": true,
            "name": "externalId",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "The owning RSX account id and the link",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/LinkOwner"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing, unrecognised, or revoked API key",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "The key is valid but lacks the scope this route requires",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No RSX ID has this external identity linked and verified",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/id/v1/links/list": {
      "get": {
        "operationId": "listLinksForAccount",
        "summary": "List an account's connected external identities",
        "description": "Requires an API key with the `id:links:list` scope.\n\nThe forward direction: every external identity connected to one RSX ID, read from the same account-link table the account's own settings page reads — there is no second copy of this data for external consumers. Each row carries `verified`, which is the difference between a provider-proven identity and a cosmetic self-asserted handle; only the former should ever carry weight in an authorization decision.\n\nCacheable for 60 seconds, privately.",
        "tags": [
          "identity"
        ],
        "security": [
          {
            "consumerApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "0198f2b1-6c2a-7c9e-9d3a-1e2f3a4b5c6d"
            },
            "required": true,
            "name": "accountId",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Connected accounts (empty when the account has none)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/AccountLink"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing, unrecognised, or revoked API key",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "The key is valid but lacks the scope this route requires",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No account with that id",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/id/v1/.well-known/jwks.json": {
      "get": {
        "operationId": "jwks",
        "summary": "JSON Web Key Set — public keys for RSX ID access tokens",
        "tags": [
          "sessions"
        ],
        "responses": {
          "200": {
            "description": "Public signing keys",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Jwks"
                }
              }
            }
          }
        }
      }
    }
  },
  "webhooks": {}
}
