BlockVectra Auth API

Login, sign-up, and sessions

Operations 3

POST /auth/siwe/challenge Get SIWE message #
POST /auth/siwe/login SIWE login (first login creates account) #
POST /auth/logout Log out current session #

Specifications

Schemas & Data

📊
JSONSchema
https://artifacts.apis.io/blockvectra/json-schema/blockvectra-freshness-envelope-schema.json
📊
JSONSchema
https://artifacts.apis.io/blockvectra/json-schema/blockvectra-token-transfer-list-envelope-schema.json
📊
JSONSchema
https://artifacts.apis.io/blockvectra/json-schema/blockvectra-address-transfer-list-envelope-schema.json
📊
JSONSchema
https://artifacts.apis.io/blockvectra/json-schema/blockvectra-tokens-batch-envelope-schema.json
📊
JSONSchema
https://artifacts.apis.io/blockvectra/json-schema/blockvectra-dex-swap-list-envelope-schema.json
📊
JSONSchema
https://artifacts.apis.io/blockvectra/json-schema/blockvectra-transaction-list-envelope-schema.json
📊
JSONSchema
https://artifacts.apis.io/blockvectra/json-schema/blockvectra-key-view-schema.json
📊
JSONSchema
https://artifacts.apis.io/blockvectra/json-schema/blockvectra-balance-response-schema.json
📊
JSONSchema
https://artifacts.apis.io/blockvectra/json-schema/blockvectra-plans-response-schema.json
📊
JSONSchema
https://artifacts.apis.io/blockvectra/json-schema/blockvectra-resets-response-schema.json
📊
JSONSchema
https://artifacts.apis.io/blockvectra/json-schema/blockvectra-identity-view-schema.json
📊
JSONSchema
https://artifacts.apis.io/blockvectra/json-schema/blockvectra-session-response-schema.json
📊
JSONSchema
https://artifacts.apis.io/blockvectra/json-schema/blockvectra-subscription-create-schema.json
📊
JSONSchema
https://artifacts.apis.io/blockvectra/json-schema/blockvectra-subscription-patch-schema.json
📊
JSONSchema
https://artifacts.apis.io/blockvectra/json-schema/blockvectra-remove-result-schema.json
📊
JSONSchema
https://artifacts.apis.io/blockvectra/json-schema/blockvectra-add-result-schema.json
📊
JSONSchema
https://artifacts.apis.io/blockvectra/json-schema/blockvectra-event-history-page-schema.json
📊
JSONSchema
https://artifacts.apis.io/blockvectra/json-schema/blockvectra-subscription-list-schema.json
📊
JSONSchema
https://artifacts.apis.io/blockvectra/json-schema/blockvectra-faucet-claim-accepted-schema.json
📊
JSONSchema
https://artifacts.apis.io/blockvectra/json-schema/blockvectra-faucet-claim-request-schema.json
📊
JSONSchema
https://artifacts.apis.io/blockvectra/json-schema/blockvectra-json-rpc-response-body-schema.json

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/blockvectra:blockvectra-auth-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

blockvectra-auth-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: BlockVectra Console Auth API
  version: 2.1.2
  description: Console account management APIs for wallet login, identities, API keys, plans, balances, charges, top-ups, usage and reset chances. Product APIs (JSON-RPC, Data API and WebSocket) do not depend on these account management APIs.
servers:
- url: https://console-api.blockvectra.com/v1
tags:
- name: Auth
  description: Login, sign-up, and sessions
paths:
  /auth/siwe/challenge:
    post:
      tags:
      - Auth
      operationId: siweChallenge
      summary: Get SIWE message
      description: Generate an EIP-4361 message and single-use nonce valid for 5 minutes. Programmatic clients omit Origin; browsers send their console Origin. Sign the returned message verbatim with an Ethereum mainnet EOA using EIP-191 personal_sign. Contract wallets and smart accounts are unsupported. purpose=login requires no session; purpose=link requires the current session.
      security:
      - {}
      - SessionToken: []
      requestBody:
        $ref: '#/components/requestBodies/SiweChallengeBody'
      responses:
        '200':
          description: Message and nonce.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SiweChallengeResponse'
              examples:
                siweChallengeLogin:
                  $ref: '#/components/examples/siweChallengeLogin'
                siweChallengeLink:
                  $ref: '#/components/examples/siweChallengeLink'
        '400':
          description: Invalid `address` or `purpose` (including invalid EIP-55 checksum), present but unconfigured `Origin` header (including empty, `null`; omitting `Origin` is programmatic mode, not an error), unknown fields.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                siweChallengeBadChecksum:
                  $ref: '#/components/examples/siweChallengeBadChecksum'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '413':
          $ref: '#/components/responses/PayloadTooLarge'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalError'
  /auth/siwe/login:
    post:
      tags:
      - Auth
      operationId: siweLogin
      summary: SIWE login (first login creates account)
      description: 'Submit raw challenge message and signature. Request `Origin` mode must match challenge: browser challenge must send same `Origin` (`https://`), programmatic challenge must omit `Origin`, otherwise returns 400 `siwe_invalid` (reason `domain_mismatch`). Verification failure returns 400 `siwe_invalid` with `reason` indicating failure type (expired, chain_mismatch, domain_mismatch, signature; nonce reuse classified as expired). Message must be submitted verbatim: modifying any content (including Chain ID) results in reason `signature`; `chain_mismatch` occurs only if configured Chain ID changes after challenge issuance. If wallet identity does not exist, an account is created (`account_created: true`, new account balance 0).


        Scope of support:

        - Supported: EOA wallets on Ethereum mainnet (Chain ID 1).

        - Not supported: Any other chains (Chain ID is embedded by server; submitting modified Chain ID fails byte-for-byte check returning 400 `siwe_invalid`, reason `signature`), contract wallets (EIP-1271), and smart accounts (eth_call verification not supported; mismatch returns siwe_invalid).'
      security: []
      requestBody:
        $ref: '#/components/requestBodies/SiweLoginBody'
      responses:
        '200':
          description: 'Login successful. Session token appears only this once; response includes `Cache-Control: no-store`.'
          headers:
            Cache-Control:
              $ref: '#/components/headers/CacheControl'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SessionResponse'
              examples:
                sessionNewAccount:
                  $ref: '#/components/examples/sessionNewAccount'
                sessionExistingAccount:
                  $ref: '#/components/examples/sessionExistingAccount'
        '400':
          description: Signature or message verification failed, unknown fields, invalid `ref`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                siweLoginInvalid:
                  $ref: '#/components/examples/siweLoginInvalid'
                siweLoginUnknownField:
                  $ref: '#/components/examples/siweLoginUnknownField'
                siweLoginInvalidRef:
                  $ref: '#/components/examples/siweLoginInvalidRef'
        '403':
          $ref: '#/components/responses/UserDisabled'
        '413':
          $ref: '#/components/responses/PayloadTooLarge'
        '429':
          $ref: '#/components/responses/SignupRateLimited'
        '500':
          $ref: '#/components/responses/InternalError'
        '503':
          $ref: '#/components/responses/SignupPaused'
  /auth/logout:
    post:
      tags:
      - Auth
      operationId: logout
      summary: Log out current session
      security:
      - SessionToken: []
      responses:
        '204':
          description: Current session revoked; subsequent requests with this token return 401.
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalError'
components:
  headers:
    RetryAfter:
      description: Suggested wait time in seconds.
      required: true
      schema:
        type: integer
        minimum: 1
      example: 6
    CacheControl:
      description: No store (included in all responses).
      required: true
      schema:
        type: string
        const: no-store
    WwwAuthenticate:
      description: '401 always includes `WWW-Authenticate: Bearer`.'
      required: true
      schema:
        type: string
        const: Bearer
  schemas:
    SignupRef:
      type:
      - string
      - 'null'
      pattern: ^[a-z0-9._-]{1,64}$
      description: 'Optional sign-up channel attribution tag, saved once only when creating a new account. Lowercase letters, digits, `.`, `_`, `-`, 1–64 characters; any other value (including uppercase, empty string) returns 400 `invalid_request` without case folding.

        '
      example: hn.launch-2026
    SiweChallengeResponse:
      type: object
      additionalProperties: false
      required:
      - nonce
      - message
      - expires_at
      properties:
        nonce:
          type: string
          pattern: ^[0-9a-f]{32}$
        message:
          $ref: '#/components/schemas/SiweMessage'
        expires_at:
          $ref: '#/components/schemas/Timestamp'
          description: Matches Expiration Time in message (Issued At + 300 s).
    SignupReferrer:
      type:
      - string
      - 'null'
      description: 'Optional referrer URL or hostname, saved once only when creating a new account, storing hostname only (lowercase, IDNA ASCII, without protocol, port, path, query). An omitted or null referrer is treated as omitted. A string from which no usable hostname can be extracted, including a blank string, is also treated as omitted (stored as null), with account creation succeeding normally. Only non-null, non-string values return 400 invalid_request.

        '
      example: https://news.ycombinator.com/item?id=1
    Timestamp:
      type: string
      format: date-time
      pattern: ^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z$
      description: RFC 3339 UTC, second precision, ending in `Z` (`2026-09-26T08:00:00Z`); no fractional seconds, without `+00:00` timezone offsets.
      example: 2026-09-26 08:00:00+00:00
    SiweMessage:
      type: string
      description: EIP-4361 message (LF line endings, no trailing newline), up to 2048 bytes.
      maxLength: 2048
      pattern: '^[a-z0-9.-]+(:[0-9]+)? wants you to sign in with your Ethereum account:\n0x[0-9a-fA-F]{40}\n\n[ -~]+\n\nURI: [!-~]+\nVersion: 1\nChain ID: [0-9]+\nNonce: [0-9a-f]{32}\nIssued At: [0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z\nExpiration Time: [0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z$'
    SiweLoginRequest:
      type: object
      additionalProperties: false
      required:
      - message
      - signature
      properties:
        message:
          $ref: '#/components/schemas/SiweMessage'
        signature:
          type: string
          pattern: ^0x[0-9a-fA-F]{130}$
          description: 65-byte ECDSA signature (r||s||v).
        ref:
          $ref: '#/components/schemas/SignupRef'
        referrer:
          $ref: '#/components/schemas/SignupReferrer'
    SessionResponse:
      type: object
      additionalProperties: false
      required:
      - session
      - account_created
      properties:
        session:
          type: object
          additionalProperties: false
          required:
          - token
          - expires_at
          - idle_timeout_secs
          properties:
            token:
              type: string
              pattern: ^rgs_[0-9a-f]{64}$
              description: Session token, displayed only this once.
            expires_at:
              $ref: '#/components/schemas/Timestamp'
              description: Absolute expiration timestamp (issued at + 7 days).
            idle_timeout_secs:
              type: integer
              description: Idle timeout (seconds).
        account_created:
          type: boolean
          description: Whether this login created a new account.
    ErrorResponse:
      type: object
      additionalProperties: false
      required:
      - error
      properties:
        error:
          type: object
          additionalProperties: false
          required:
          - code
          - message
          properties:
            code:
              type: string
              enum:
              - invalid_request
              - siwe_invalid
              - oauth_invalid
              - login_code_invalid
              - unauthenticated
              - user_disabled
              - not_found
              - provider_disabled
              - method_not_allowed
              - identity_in_use
              - identity_limit_reached
              - last_identity
              - key_not_active
              - key_limit_reached
              - no_reset_available
              - payload_too_large
              - rate_limited
              - signup_rate_limited
              - signup_paused
              - usage_unavailable
              - service_unavailable
              - internal
            message:
              type: string
              description: Human-readable explanation, subject to wording adjustments.
            reason:
              type: string
              enum:
              - expired
              - chain_mismatch
              - domain_mismatch
              - signature
              - active_keys
              - daily_creations
              - invalid_username
              - nothing_to_reset
              - per_ip
              - global
              - cu_cap
              - expires_at
              - audience
              description: 'Machine-readable reason (siwe_invalid: expired, chain_mismatch, domain_mismatch, signature; key_limit_reached: active_keys; rate_limited: daily_creations for 24h key creation limit; invalid_request: invalid_username, cu_cap, expires_at; no_reset_available: nothing_to_reset when balance is already at or above target; signup_rate_limited: per_ip or global).'
            limit:
              type: integer
              description: Limit threshold value (e.g. active_keys limit for key_limit_reached).
    SiweChallengeRequest:
      type: object
      additionalProperties: false
      required:
      - address
      - purpose
      properties:
        address:
          type: string
          pattern: ^0x[0-9a-fA-F]{40}$
          description: EOA address. Must be a valid EIP-55 checksum if mixed case.
        purpose:
          type: string
          enum:
          - login
          - link
          description: '`login` for login / sign-up; `link` to link wallet to current session user (requires session).'
  examples:
    siweLoginInvalidRef:
      summary: Invalid ref (contains uppercase), account not created
      value:
        error:
          code: invalid_request
          message: invalid request
    reqSiweLoginBadRef:
      summary: ref contains uppercase
      value:
        message: 'console.blockvectra.com wants you to sign in with your Ethereum account:

          0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266


          Sign in to the BlockVectra RPC console.


          URI: https://console.blockvectra.com

          Version: 1

          Chain ID: 1

          Nonce: 3f7c0a9e5b1d4c2a8e6f0b3d9a7c5e1f

          Issued At: 2026-09-26T08:00:00Z

          Expiration Time: 2026-09-26T08:05:00Z'
        signature: '0x5f2a8c3e1d9b7f604a2e8c1b3d5f7a9e0c2b4d6f8a1c3e5b7d9f0a2c4e6b8d1f3a5c7e9b0d2f4a6c8e1b3d5f7a9c0e2b4d6f8a1c3e5b7d9f0a2c4e6b8d1f3a5c1c'
        ref: Twitter
    errUnauthenticated:
      summary: Invalid session (missing, malformed, unknown, expired, or revoked)
      value:
        error:
          code: unauthenticated
          message: missing or invalid session token
    reqSiweLoginAttributed:
      summary: With sign-up attribution (saved only on new account creation)
      value:
        message: 'console.blockvectra.com wants you to sign in with your Ethereum account:

          0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266


          Sign in to the BlockVectra RPC console.


          URI: https://console.blockvectra.com

          Version: 1

          Chain ID: 1

          Nonce: 3f7c0a9e5b1d4c2a8e6f0b3d9a7c5e1f

          Issued At: 2026-09-26T08:00:00Z

          Expiration Time: 2026-09-26T08:05:00Z'
        signature: '0x5f2a8c3e1d9b7f604a2e8c1b3d5f7a9e0c2b4d6f8a1c3e5b7d9f0a2c4e6b8d1f3a5c7e9b0d2f4a6c8e1b3d5f7a9c0e2b4d6f8a1c3e5b7d9f0a2c4e6b8d1f3a5c1c'
        ref: hn.launch-2026
        referrer: https://news.ycombinator.com/item?id=1
    reqChallengeBadChecksum:
      summary: Mixed case but invalid EIP-55 checksum (valid format, server returns 400)
      value:
        address: '0xF39Fd6e51aad88F6F4ce6aB8827279cffFb92266'
        purpose: login
    siweLoginUnknownField:
      summary: Request body contains undefined fields
      value:
        error:
          code: invalid_request
          message: unknown field `chain_id`
    reqChallengeLogin:
      summary: Challenge for login
      value:
        address: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266'
        purpose: login
    errInternal:
      summary: Internal error
      value:
        error:
          code: internal
          message: internal error
    errUnauthenticatedLinkChallenge:
      summary: purpose=link without session
      value:
        error:
          code: unauthenticated
          message: missing or invalid session token
    reqSiweVerifyUnknownField:
      summary: Contains undefined fields
      value:
        message: 'console.blockvectra.com wants you to sign in with your Ethereum account:

          0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266


          Sign in to the BlockVectra RPC console.


          URI: https://console.blockvectra.com

          Version: 1

          Chain ID: 1

          Nonce: 3f7c0a9e5b1d4c2a8e6f0b3d9a7c5e1f

          Issued At: 2026-09-26T08:00:00Z

          Expiration Time: 2026-09-26T08:05:00Z'
        signature: '0x5f2a8c3e1d9b7f604a2e8c1b3d5f7a9e0c2b4d6f8a1c3e5b7d9f0a2c4e6b8d1f3a5c7e9b0d2f4a6c8e1b3d5f7a9c0e2b4d6f8a1c3e5b7d9f0a2c4e6b8d1f3a5c1c'
        chain_id: 1
    reqChallengeUnknownPurpose:
      summary: purpose is not login/link
      value:
        address: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266'
        purpose: register
    payloadTooLarge:
      summary: Payload too large
      value:
        error:
          code: payload_too_large
          message: payload too large
    sessionNewAccount:
      summary: First login with new wallet, account created
      value:
        session:
          token: rgs_4f2d0c3b9a8e7d6c5b4a39281706f5e4d3c2b1a09f8e7d6c5b4a3928170605f4
          expires_at: 2026-10-03 08:00:00+00:00
          idle_timeout_secs: 86400
        account_created: true
    siweChallengeLogin:
      summary: Challenge message for login
      value:
        nonce: 3f7c0a9e5b1d4c2a8e6f0b3d9a7c5e1f
        message: 'console.blockvectra.com wants you to sign in with your Ethereum account:

          0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266


          Sign in to the BlockVectra RPC console.


          URI: https://console.blockvectra.com

          Version: 1

          Chain ID: 1

          Nonce: 3f7c0a9e5b1d4c2a8e6f0b3d9a7c5e1f

          Issued At: 2026-09-26T08:00:00Z

          Expiration Time: 2026-09-26T08:05:00Z'
        expires_at: 2026-09-26 08:05:00+00:00
    reqSiweVerify:
      summary: Submit raw message and signature
      value:
        message: 'console.blockvectra.com wants you to sign in with your Ethereum account:

          0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266


          Sign in to the BlockVectra RPC console.


          URI: https://console.blockvectra.com

          Version: 1

          Chain ID: 1

          Nonce: 3f7c0a9e5b1d4c2a8e6f0b3d9a7c5e1f

          Issued At: 2026-09-26T08:00:00Z

          Expiration Time: 2026-09-26T08:05:00Z'
        signature: '0x5f2a8c3e1d9b7f604a2e8c1b3d5f7a9e0c2b4d6f8a1c3e5b7d9f0a2c4e6b8d1f3a5c7e9b0d2f4a6c8e1b3d5f7a9c0e2b4d6f8a1c3e5b7d9f0a2c4e6b8d1f3a5c1c'
    sessionExistingAccount:
      summary: Subsequent login with existing wallet identity
      value:
        session:
          token: rgs_9a8b7c6d5e4f30211203f4e5d6c7b8a99a8b7c6d5e4f30211203f4e5d6c7b8a9
          expires_at: 2026-10-03 09:00:00+00:00
          idle_timeout_secs: 86400
        account_created: false
    siweLoginInvalid:
      summary: 'Invalid signature (with reason: signature)'
      value:
        error:
          code: siwe_invalid
          message: invalid SIWE message or signature
          reason: signature
    siweChallengeBadChecksum:
      summary: Invalid EIP-55 checksum
      value:
        error:
          code: invalid_request
          message: address is not a valid EIP-55 checksum address
    reqChallengeLink:
      summary: Challenge for linking (requires session)
      value:
        address: '0x70997970C51812dc3A010C7d01b50e0d17dc79C8'
        purpose: link
    errSignupRateLimited:
      summary: New sign-up budget exhausted for same network (existing identities can log in)
      value:
        error:
          code: signup_rate_limited
          message: too many new accounts were created from this network recently; retry in 3600 seconds
          reason: per_ip
    errUserDisabled:
      summary: Account disabled
      value:
        error:
          code: user_disabled
          message: this user has been disabled
    errMethodNotAllowed:
      summary: Method not allowed
      value:
        error:
          code: method_not_allowed
          message: method not allowed
    errRateLimited:
      summary: Rate limit exceeded
      value:
        error:
          code: rate_limited
          message: rate limit exceeded
    siweChallengeLink:
      summary: Challenge message for linking (statement specifies account ID)
      value:
        nonce: 8e1f4c7a0b3d6e9f2a5c8b1d4e7f0a3c
        message: 'console.blockvectra.com wants you to sign in with your Ethereum account:

          0x70997970C51812dc3A010C7d01b50e0d17dc79C8


          Link this wallet to BlockVectra RPC console account acct_ejb7hrlrentyincbnwemctnhde.


          URI: https://console.blockvectra.com

          Version: 1

          Chain ID: 1

          Nonce: 8e1f4c7a0b3d6e9f2a5c8b1d4e7f0a3c

          Issued At: 2026-09-26T08:10:00Z

          Expiration Time: 2026-09-26T08:15:00Z'
        expires_at: 2026-09-26 08:15:00+00:00
    errSignupPaused:
      summary: New account creation temporarily unavailable
      value:
        error:
          code: signup_paused
          message: new signups are temporarily paused
  requestBodies:
    SiweChallengeBody:
      required: true
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/SiweChallengeRequest'
          examples:
            reqChallengeLogin:
              $ref: '#/components/examples/reqChallengeLogin'
            reqChallengeLink:
              $ref: '#/components/examples/reqChallengeLink'
            reqChallengeBadChecksum:
              $ref: '#/components/examples/reqChallengeBadChecksum'
            reqChallengeUnknownPurpose:
              $ref: '#/components/examples/reqChallengeUnknownPurpose'
    SiweLoginBody:
      required: true
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/SiweLoginRequest'
          examples:
            reqSiweVerify:
              $ref: '#/components/examples/reqSiweVerify'
            reqSiweLoginAttributed:
              $ref: '#/components/examples/reqSiweLoginAttributed'
            reqSiweLoginBadRef:
              $ref: '#/components/examples/reqSiweLoginBadRef'
            reqSiweVerifyUnknownField:
              $ref: '#/components/examples/reqSiweVerifyUnknownField'
  responses:
    MethodNotAllowed:
      description: Path exists but HTTP method does not match.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            errMethodNotAllowed:
              $ref: '#/components/examples/errMethodNotAllowed'
    PayloadTooLarge:
      description: Request body exceeds 64 KiB limit. Exceeding this limit returns 413 (`payload_too_large`).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            payloadTooLarge:
              $ref: '#/components/examples/payloadTooLarge'
    InternalError:
      description: Internal server error.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            errInternal:
              $ref: '#/components/examples/errInternal'
    SignupPaused:
      description: New account creation temporarily unavailable; affects new registrations only; existing users log in normally.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            errSignupPaused:
              $ref: '#/components/examples/errSignupPaused'
    TooManyRequests:
      description: Rate limit exceeded.
      headers:
        Retry-After:
          $ref: '#/components/headers/RetryAfter'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            errRateLimited:
              $ref: '#/components/examples/errRateLimited'
    UserDisabled:
      description: Account has been disabled; login not permitted.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            errUserDisabled:
              $ref: '#/components/examples/errUserDisabled'
    Unauthorized:
      description: Missing or invalid session (without distinguishing cause).
      headers:
        WWW-Authenticate:
          $ref: '#/components/headers/WwwAuthenticate'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            errUnauthenticated:
              $ref: '#/components/examples/errUnauthenticated'
            errUnauthenticatedLinkChallenge:
              $ref: '#/components/examples/errUnauthenticatedLinkChallenge'
    SignupRateLimited:
      description: 'Rate limit exceeded during login: request rate limit is `rate_limited`; sign-up budget exhaustion is `signup_rate_limited`, with `reason` `per_ip` (same network prefix) or `global` (all sources combined).'
      headers:
        Retry-After:
          $ref: '#/components/headers/RetryAfter'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            errRateLimited:
              $ref: '#/components/examples/errRateLimited'
            errSignupRateLimited:
              $ref: '#/components/examples/errSignupRateLimited'
  securitySchemes:
    SessionToken:
      type: http
      scheme: bearer
      bearerFormat: rgs_<64-character lowercase hex>
      description: '`Authorization: Bearer rgs_...`, issued by `POST /auth/siwe/login` or `POST /auth/oauth/token`. Absolute TTL 7 days,

        idle 24 hours. Invalid returns 401 `unauthenticated` with `WWW-Authenticate: Bearer`.

        '