Euler Finance Auth API

Authentication and authorization conventions used across the API, including API keys, admin secrets, and rate-limit behavior.

OpenAPI Specification

euler-auth-api-openapi.yml Raw ↑
openapi: 3.1.0
info:
  title: Euler Data API (V3) Accounts Auth API
  version: 3.0.0
  description: "API specification for Euler Data v3. This spec defines the current\nresource-oriented contract for the platform, with emphasis on consistent\nschemas, predictable REST semantics, caching, observability, and a uniform\ndeveloper experience.\n\nMigration notes\n- Euler Data v3 is not a path-for-path clone of v1/v2. Some endpoints map\n  directly, some require multiple v3 calls, and some legacy aggregates were\n  intentionally removed.\n- The live [migration guide](/v3/docs/migration) explains how legacy v1/v2\n  endpoints and payloads map into the v3 resource model.\n- Important semantic changes:\n  - Vault base APY and rewards APY are exposed separately in v3.\n  - Account positions are flattened into account-vault rows instead of the\n    legacy nested sub-account shape.\n  - All supported API paths live under `/v3`; legacy paths return `410`.\n  - Summary endpoints prefer smaller, focused resources over large\n    BFF-style payloads.\n\nBase path: /v3\n\nConventions\n- JSON field naming: camelCase\n- Addresses: accept lowercase or checksum; responses are EIP-55 checksummed\n- Public APY values (`*Apy`, `apy*`): percent numbers with 6 decimal places (e.g., 5.123456 = 5.123456%)\n- Contract interest-rate fields (`borrowAPY`, `supplyAPY` in `interestRates`): decimal strings in contract fraction units\n- Ratios (utilization, LTV, etc.): numbers with 6 decimal places\n- Response timestamps: ISO-8601 strings (UTC). Some legacy fields still expose unix\n  seconds for compatibility and include `*Iso` companions.\n- Query time ranges: unix seconds (from/to)\n\nUnit policy\n- v3 separates market metadata from contract verdicts by both name and type.\n- Market-normalized USD prices and USD values are JSON numbers. These are values\n  derived from off-chain pricing, cached price snapshots, or API-level market math.\n  This includes `/v3/prices`, token price routes, vault/earn/protocol USD totals,\n  portfolio market values, portfolio USD liquidation/risk fields such as\n  `liabilityValueUsd`, `totalCollateralValueUsd`, `borrowLiquidationPriceUsd`,\n  and `collateralLiquidationPricesUsd`, and vault holder `assetsUsd`.\n- Contract-derived oracle and raw account-liquidity verdict values are exact strings.\n  These preserve the integer value used by contracts, normalized to 18 decimals\n  for API exposure. Oracle prices are quoted in the vault unit of account, which\n  can be USD, ETH, or another asset. This includes `/v3/oracles/prices`, raw\n  account-liquidity `liabilityValue` and `totalCollateralValue` objects,\n  `liabilityValueBorrowing`, `liabilityValueLiquidation`, and collateral verdict\n  values.\n- On-chain token quantities are bigint strings in their native unit scale. This\n  includes amounts, balances, shares, assets, borrows, reward amounts, liquidation\n  repay/yield amounts, and block numbers.\n- Caps are also bigint strings, but EVK caps are exposed as resolved underlying\n  asset-unit amounts rather than packed contract config words.\n- LTV config values use canonical basis-point strings. Legacy decimal aliases\n  may remain on config-history payloads for compatibility when explicitly named.\n\nRate limiting\n- Optional API keys for higher limits\n- Default limits are configurable; current defaults: free tier 100 req/min (IP-based)\n  and authenticated 1000 req/min (per API key), 60s window.\n- By default, proxy headers are not trusted for IP identity unless explicitly enabled.\n- Redis failures default to fail-closed (503) for strict enforcement; fail-open is opt-in.\n- RateLimit-* (IETF draft-6) and legacy X-RateLimit-* headers are returned.\n\nCORS\n- Public API responses use wildcard CORS, including preflight responses for unsafe methods.\n- Unsafe methods with request bodies must use a JSON media type.\n\nCaching\n- Cache-Control headers are returned for cacheable endpoints.\n- Defaults (may be adjusted in config):\n  - Prices: 300s\n  - APYs: 600s\n  - Rewards: 900s\n  - General responses: 60s (short 30s, long 300s)\n\nErrors\n- All errors use a standard envelope: { error: { code, message, requestId, details? } }\n- Domain error codes are documented in this spec.\n- JSON request bodies must use `Content-Type: application/json` or another `application/*+json` media type.\n- Request bodies larger than 1 MiB are rejected before route parsing with `413 PAYLOAD_TOO_LARGE`.\n"
servers:
- url: /
  description: Current environment
security: []
tags:
- name: Auth
  description: Authentication and authorization conventions used across the API, including API keys, admin secrets, and rate-limit behavior.
paths:
  /v3/auth/login:
    get:
      tags:
      - Auth
      summary: Start platform-operator Google SSO
      description: Redirects the browser to Google OAuth/OIDC and sets a signed OAuth state cookie.
      x-status: implemented
      responses:
        '302':
          description: Redirect to configured Google OAuth authorization URL.
          headers:
            Location:
              description: Google authorization URL.
              schema:
                type: string
                format: uri
            Set-Cookie:
              description: Signed OAuth state cookie with httpOnly, SameSite, path, and expiry.
              schema:
                type: string
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
      operationId: startPlatformAuthLogin
  /v3/auth/callback:
    get:
      tags:
      - Auth
      summary: Complete platform-operator Google SSO callback
      description: Validates state, nonce, Google ID-token claims, and active platform-admin access.
      x-status: implemented
      parameters:
      - name: code
        in: query
        required: true
        schema:
          type: string
        description: OAuth authorization code. Never returned in responses.
      - name: state
        in: query
        required: true
        schema:
          type: string
        description: OAuth anti-forgery state bound to the signed state cookie.
      responses:
        '302':
          description: Successful callback; session and CSRF cookies are set, then browser is redirected.
          headers:
            Location:
              description: Configured post-login redirect URL.
              schema:
                type: string
                format: uri
            Set-Cookie:
              description: Signed httpOnly session cookie, readable CSRF cookie, and cleared OAuth state cookie.
              schema:
                type: string
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
        '400':
          description: Invalid callback, state, nonce, or ID token.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Google identity is not an active platform admin.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      operationId: completePlatformAuthCallback
  /v3/auth/session:
    get:
      tags:
      - Auth
      summary: Get current platform-operator session
      x-status: implemented
      security:
      - PlatformSession: []
      responses:
        '200':
          description: Active platform-admin session identity.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
          content:
            application/json:
              schema:
                type: object
                required:
                - data
                - meta
                properties:
                  data:
                    $ref: '#/components/schemas/PlatformAuthSession'
                  meta:
                    $ref: '#/components/schemas/PaginationMeta'
        '401':
          description: Missing, invalid, or expired platform-admin session.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Authenticated session exists, but platform-admin access is not active.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      operationId: getPlatformAuthSession
  /v3/auth/logout:
    post:
      tags:
      - Auth
      summary: End current platform-operator session
      x-status: implemented
      security:
      - PlatformSession: []
        PlatformCsrf: []
      responses:
        '200':
          description: Session cookies were cleared.
          headers:
            Set-Cookie:
              description: Expired session and CSRF cookies.
              schema:
                type: string
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
          content:
            application/json:
              schema:
                type: object
                required:
                - data
                - meta
                properties:
                  data:
                    type: object
                    required:
                    - loggedOut
                    properties:
                      loggedOut:
                        type: boolean
                  meta:
                    $ref: '#/components/schemas/PaginationMeta'
        '401':
          description: Invalid signed platform-admin session.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Missing or mismatched CSRF token, or inactive platform-admin access.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      operationId: logoutPlatformAuthSession
  /v3/platform-admins:
    post:
      tags:
      - Auth
      summary: Grant platform-admin access
      description: 'Creates an active platform-admin access row for a Google email address.

        Requires a valid platform session and CSRF token because this is an unsafe

        cookie-authenticated write.

        '
      x-status: implemented
      security:
      - PlatformSession: []
        PlatformCsrf: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PlatformAdminAccessRequest'
      responses:
        '200':
          description: Existing revoked platform-admin access was reactivated.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
          content:
            application/json:
              schema:
                type: object
                required:
                - data
                - meta
                properties:
                  data:
                    $ref: '#/components/schemas/PlatformAdminCreateAccessResult'
                  meta:
                    $ref: '#/components/schemas/PaginationMeta'
        '201':
          description: Platform-admin access was created.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
          content:
            application/json:
              schema:
                type: object
                required:
                - data
                - meta
                properties:
                  data:
                    $ref: '#/components/schemas/PlatformAdminCreateAccessResult'
                  meta:
                    $ref: '#/components/schemas/PaginationMeta'
        '400':
          description: Malformed JSON request body.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Missing, invalid, or expired platform-admin session.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Inactive platform-admin access, missing CSRF token, or mismatched CSRF token.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '409':
          description: Platform-admin access already exists.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '422':
          description: Missing or invalid Google email.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      operationId: createPlatformAdminAccess
  /v3/platform-admins/revoke:
    post:
      tags:
      - Auth
      summary: Revoke platform-admin access
      description: 'Soft-revokes platform-admin access for a Google email address. Requires a

        valid platform session and CSRF token because this is an unsafe

        cookie-authenticated write.

        '
      x-status: implemented
      security:
      - PlatformSession: []
        PlatformCsrf: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PlatformAdminAccessRequest'
      responses:
        '200':
          description: Platform-admin access was revoked.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
          content:
            application/json:
              schema:
                type: object
                required:
                - data
                - meta
                properties:
                  data:
                    $ref: '#/components/schemas/PlatformAdminRevokeAccessResult'
                  meta:
                    $ref: '#/components/schemas/PaginationMeta'
        '400':
          description: Malformed JSON request body.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Missing, invalid, or expired platform-admin session.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: Inactive platform-admin access, missing CSRF token, or mismatched CSRF token.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Platform-admin access was not found.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '409':
          description: Platform-admin access was already revoked.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '422':
          description: Missing or invalid Google email.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      operationId: revokePlatformAdminAccess
  /v3/toolbox/admin/api-keys:
    get:
      tags:
      - Auth
      summary: List API keys for toolbox Admin
      description: Lists API key metadata for the toolbox Admin screen. Requires an active platform-admin session and a Google email present in `TOOLBOX_ADMIN_EMAILS`.
      x-status: implemented
      security:
      - PlatformSession: []
      responses:
        '200':
          description: API key metadata visible to toolbox admins.
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
          content:
            application/json:
              schema:
                type: object
                required:
                - data
                - meta
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/ApiKeyResponse'
                  meta:
                    $ref: '#/components/schemas/PaginationMeta'
        '401':
          $ref: '#/components/responses/Error401'
        '403':
          $ref: '#/components/responses/Error403'
        '500':
          $ref: '#/components/responses/Error500'
      operationId: getToolboxAdminApiKeys
  /v3/admin/api-keys:
    post:
      tags:
      - Auth
      summary: Create an API key (admin)
      x-status: implemented
      security:
      - AdminSecret: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ApiKeyCreateRequest'
      responses:
        '201':
          description: API key created
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/ApiKeyCreateResponse'
        '400':
          $ref: '#/components/responses/Error400'
        '401':
          $ref: '#/components/responses/Error401'
        '403':
          $ref: '#/components/responses/Error403'
        '413':
          $ref: '#/components/responses/Error413'
        '415':
          $ref: '#/components/responses/Error415'
        '500':
          $ref: '#/components/responses/Error500'
      operationId: postAdminApiKeys
    get:
      tags:
      - Auth
      summary: List API keys (admin)
      x-status: implemented
      security:
      - AdminSecret: []
      responses:
        '200':
          description: API keys
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/ApiKeyResponse'
        '401':
          $ref: '#/components/responses/Error401'
        '403':
          $ref: '#/components/responses/Error403'
        '500':
          $ref: '#/components/responses/Error500'
      operationId: getAdminApiKeys
  /v3/admin/api-keys/{id}:
    get:
      tags:
      - Auth
      summary: Get API key by id (admin)
      x-status: implemented
      security:
      - AdminSecret: []
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
      responses:
        '200':
          description: API key
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/ApiKeyResponse'
        '401':
          $ref: '#/components/responses/Error401'
        '403':
          $ref: '#/components/responses/Error403'
        '404':
          $ref: '#/components/responses/Error404'
        '500':
          $ref: '#/components/responses/Error500'
      operationId: getAdminApiKeysById
    patch:
      tags:
      - Auth
      summary: Update API key (admin)
      x-status: implemented
      security:
      - AdminSecret: []
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                rateLimit:
                  type: integer
                isActive:
                  type: boolean
                keyType:
                  type: string
                  enum:
                  - standard
                  - curator
                scopeMode:
                  type: string
                  enum:
                  - all_vaults
                  - allowlist
                vaultAllowlist:
                  type: array
                  items:
                    type: object
                    required:
                    - chainId
                    - vaultAddress
                    properties:
                      chainId:
                        type: integer
                      vaultAddress:
                        type: string
      responses:
        '200':
          description: Updated
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
        '400':
          $ref: '#/components/responses/Error400'
        '401':
          $ref: '#/components/responses/Error401'
        '403':
          $ref: '#/components/responses/Error403'
        '404':
          $ref: '#/components/responses/Error404'
        '413':
          $ref: '#/components/responses/Error413'
        '415':
          $ref: '#/components/responses/Error415'
        '500':
          $ref: '#/components/responses/Error500'
      operationId: patchAdminApiKeysById
    delete:
      tags:
      - Auth
      summary: Revoke API key (admin)
      x-status: implemented
      security:
      - AdminSecret: []
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
      responses:
        '200':
          description: Revoked
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
        '401':
          $ref: '#/components/responses/Error401'
        '403':
          $ref: '#/components/responses/Error403'
        '404':
          $ref: '#/components/responses/Error404'
        '500':
          $ref: '#/components/responses/Error500'
      operationId: deleteAdminApiKeysById
  /v3/admin/api-keys/{id}/usage:
    get:
      tags:
      - Auth
      summary: Usage stats for an API key (admin)
      x-status: implemented
      security:
      - AdminSecret: []
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
      - name: days
        in: query
        required: false
        schema:
          type: integer
      responses:
        '200':
          description: Usage stats
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/ApiKeyUsageResponse'
        '401':
          $ref: '#/components/responses/Error401'
        '403':
          $ref: '#/components/responses/Error403'
        '404':
          $ref: '#/components/responses/Error404'
        '500':
          $ref: '#/components/responses/Error500'
      operationId: getAdminApiKeysByIdUsage
components:
  schemas:
    ApiKeyUsageResponse:
      type: object
      required:
      - period
      - summary
      - endpoints
      properties:
        period:
          type: object
          required:
          - days
          - since
          properties:
            days:
              type: integer
            since:
              type: string
              format: date-time
        summary:
          type: object
          required:
          - totalRequests
          - avgResponseTimeMs
          - errorCount
          properties:
            totalRequests:
              type: integer
            avgResponseTimeMs:
              type: integer
            errorCount:
              type: integer
        endpoints:
          type: array
          items:
            type: object
            required:
            - endpoint
            - method
            - count
            - avgResponseTime
            properties:
              endpoint:
                type: string
              method:
                type: string
              count:
                type: integer
              avgResponseTime:
                type: integer
    PlatformAdminAccess:
      type: object
      required:
      - id
      - googleEmail
      - createdAt
      - revokedAt
      properties:
        id:
          type: string
          format: uuid
        googleEmail:
          type: string
          format: email
        createdAt:
          type: string
          format: date-time
        revokedAt:
          type: string
          format: date-time
          nullable: true
    ApiKeyResponse:
      type: object
      required:
      - id
      - name
      - keyType
      - rateLimit
      - isActive
      - createdAt
      properties:
        id:
          type: string
        keyPrefix:
          type: string
        name:
          type: string
        ownerEmail:
          type: string
          nullable: true
        keyType:
          type: string
          enum:
          - standard
          - curator
        scopeMode:
          type: string
          enum:
          - all_vaults
          - allowlist
          nullable: true
        vaultAllowlist:
          type: array
          items:
            type: object
            required:
            - chainId
            - vaultAddress
            properties:
              chainId:
                type: integer
              vaultAddress:
                type: string
        rateLimit:
          type: integer
        isActive:
          type: boolean
        createdAt:
          type: string
          format: date-time
        lastUsedAt:
          type: string
          format: date-time
          nullable: true
        expiresAt:
          type: string
          format: date-time
          nullable: true
    PlatformAdminAccessRequest:
      type: object
      additionalProperties: false
      required:
      - googleEmail
      properties:
        googleEmail:
          type: string
          format: email
          description: Google Workspace email address to grant or revoke.
    ErrorResponse:
      type: object
      required:
      - error
      properties:
        error:
          type: object
          required:
          - code
          - message
          - requestId
          properties:
            code:
              type: string
              description: 'Domain error code. Examples:

                - INVALID_ADDRESS

                - CHAIN_NOT_SUPPORTED

                - VAULT_NOT_FOUND

                - TOKEN_NOT_FOUND

                - ACCOUNT_NOT_FOUND

                - VALIDATION_ERROR

                - RATE_LIMIT_EXCEEDED

                - UNSUPPORTED_MEDIA_TYPE

                - UNAUTHORIZED

                - FORBIDDEN

                - INTERNAL_ERROR

                '
            message:
              type: string
            requestId:
              type: string
            details:
              type: object
              additionalProperties: true
    ApiKeyCreateRequest:
      type: object
      required:
      - name
      properties:
        name:
          type: string
        ownerEmail:
          type: string
          format: email
        keyType:
          type: string
          enum:
          - standard
          - curator
          default: standard
        scopeMode:
          type: string
          enum:
          - all_vaults
          - allowlist
        vaultAllowlist:
          type: array
          items:
            type: object
            required:
            - chainId
            - vaultAddress
            properties:
              chainId:
                type: integer
              vaultAddress:
                type: string
        rateLimit:
          type: integer
        expiresInDays:
          type: integer
    ApiKeyCreateResponse:
      type: object
      required:
      - message
      - key
      - keyPrefix
      - id
      - name
      - keyType
      - rateLimit
      properties:
        message:
          type: string
        key:
          type: string
        keyPrefix:
          type: string
        id:
          type: string
        name:
          type: string
        keyType:
          type: string
          enum:
          - standard
          - curator
        scopeMode:
          type: string
          enum:
          - all_vaults
          - allowlist
          nullable: true
        vaultAllowlist:
          type: array
          items:
            type: object
            required:
            - chainId
            - vaultAddress
            properties:
              chainId:
                type: integer
              vaultAddress:
                type: string
        rateLimit:
          type: integer
        expiresAt:
          type: string
          format: date-time
          nullable: true
    PlatformAdminCreateAccessResult:
      type: object
      required:
      - admin
      - state
      properties:
        admin:
          $ref: '#/components/schemas/PlatformAdminAccess'
        state:
          type: string
          enum:
          - created
          - reactivated
    PlatformAdminRevokeAccessResult:
      type: object
      required:
      - admin
      - state
      properties:
        admin:
          $ref: '#/components/schemas/PlatformAdminAccess'
        state:
          type: string
          enum:
          - revoked
    PlatformAuthSession:
      type: object
      required:
      - platformAdminId
      - googleEmail
      - googleSubject
      - active
      - expiresAt
      properties:
        platformAdminId:
          type: string
          format: uuid
        googleEmail:
          type: string
          format: email
        googleSubject:
          type: string
        active:
          type: boolean
          const: true
        expiresAt:
          type: string
          format: date-time
    PaginationMeta:
      type: object
      required:
      - timestamp
      properties:
        total:
          type: integer
          description: Exact total count when the endpoint provides one.
        hasMore:
          type: boolean
          description: Indicates whether another page exists beyond the current page.
        offset:
          type: integer
        limit:
          type: integer
          description: Echoed page size after endpoint-side clamping.
        timestamp:
          type: string
        

# --- truncated at 32 KB (34 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/euler/refs/heads/main/openapi/euler-auth-api-openapi.yml