# raw swagger spec link: # https://raw.githubusercontent.com/JanssenProject/jans-fido2/master/docs/jansFido2Swagger.yaml # https://gluu.org/swagger-ui/?url=https://raw.githubusercontent.com/JanssenProject/jans-fido2/master/docs/jansFido2Swagger.yaml openapi: 3.0.1 info: title: Janssen Fido2 description: Janssen Fido2 - FIDO 2.0 is an open authentication standard that enables leveraging common devices to authenticate to online services in both mobile and desktop environments. contact: name: Contact url: https://github.com/JanssenProject/jans/discussions license: name: License url: https://github.com/JanssenProject/jans/blob/main/LICENSE version: "OAS Version" servers: - url: https://jans.local.io tags: - name: About description: Janssen includes a FIDO2 component to implement a two-step, two-factor authentication (2FA) with username / password as the first step, and any FIDO2 device as the second step. - name: FIDO2 configuration - name: FIDO2 Assertion - name: FIDO2 Attestation - name: FIDO2 Metrics description: Metrics and analytics API for FIDO2/Passkey operations (registrations, authentications, adoption, performance, devices, errors, trends). - name: FIDO2 Trust description: Read-only visibility into the attestation policy the server is applying. Diagnostics only — these endpoints never change attestation behaviour. paths: /jans-fido2/restv1/configuration: get: tags: - FIDO2 configuration summary: FIDO2 configuration description: FIDO2 configuration operationId: get-fido2-configuration responses: 200: description: OK content: application/json: schema: title: FIDO2 configuration description: FIDO2 configuration. required: - version - issuer - attestation properties: version: type: string description: The version of the FIDO2 U2F core protocol to which this server conforms. The value MUST be the string 1.0. issuer: type: string description: A URI indicating the party operating the FIDO U2F server. attestation: type: array items: type: object description: list of fido2 attestation endpoints properties: base_path: type: string description: fido2 attestation endpoint options_endpoint: type: string description: fido2 attestation options endpoint result_endpoint: type: string description: fido2 attestation result endpoint assertion: type: array items: type: object description: list of fido2 assertion endpoints properties: base_path: type: string description: fido2 assertion endpoint options_endpoint: type: string description: fido2 assertion options endpoint result_endpoint: type: string description: fido2 assertion result endpoint 403: $ref: '#/components/responses/AccessDenied' 406: $ref: '#/components/responses/NotAcceptable' 500: $ref: '#/components/responses/InternalServerError' /jans-fido2/restv1/assertion/options: post: tags: - FIDO2 Assertion summary: FIDO2 Assertion Options description: FIDO2 Assertion Options operationId: options requestBody: content: application/json: schema: title: AssertionOptions description: An object that contains the extensions to enable, and the options to use for each of them. type: object required: - username properties: username: type: string userVerification: type: string documentDomain: type: string extensions: type: string session_id: type: string responses: 200: description: OK content: application/json: schema: title: AssertionOptionsResponse type: object required: - challenge - user - allowCredentials - userVerification - extensions properties: challenge: type: string description: Websafe-base64 encoding of the challenge. user: type: string description: username allowCredentials: type: array items: type: string example: - type - transports - id userVerification: type: string extensions: type: object rpId: type: string description: Document domain. status: type: string errorMessage: type: string 403: $ref: '#/components/responses/AccessDenied' 500: $ref: '#/components/responses/InternalServerError' /jans-fido2/restv1/assertion/result: post: tags: - FIDO2 Assertion summary: FIDO2 Assertion Result - Parses and validates an assertion response from the client. description: FIDO2 Assertion Result. operationId: result requestBody: content: application/json: schema: title: AssertionOptions type: object required: - id - type - response - rawId properties: id: type: string description: The base64url encoded id type: type: string example: - public-key rawId: type: string description: The base64url encoded rawId returned by the client. If res.rawId is missing, res.id will be used instead. If both are missing an error will be thrown. response: type: object properties: userHandle: type: string description: The base64url encoded userHandle returned by the client. May be null or an empty string. clientDataJSON: type: string description: The base64url encoded clientDataJSON returned by the client. authenticatorData: type: string description: The base64url encoded authenticator Data. May be null or an empty string. signature: type: string description: To verify signature. responses: 200: description: OK content: application/json: schema: title: AssertionVerifyResponse type: object required: - status properties: status: type: string errorMessage: type: string authenticatedCredentials: type: object properties: type: type: string id: type: string transports: type: array description: list of transports. items: type: string example: - net - qr - usb 403: $ref: '#/components/responses/AccessDenied' 500: $ref: '#/components/responses/InternalServerError' /jans-fido2/restv1/attestation/options: post: tags: - FIDO2 Attestation summary: Create new registration. description: Create new registration. operationId: attestation-options requestBody: content: application/json: schema: title: AttestationOptions description: An object containing various options for the option creation type: object required: - username - displayName - attestation properties: username: type: string displayName: type: string attestation: type: string format: enum - direct - indirect - none documentDomain: type: string timeout: type: integer extensions: type: object authenticatorSelection: type: object properties: authenticatorAttachment: type: string format: enum - platform - cross-platform userVerification: type: string format: enum - direct - indirect - none requireResidentKey: type: boolean responses: 200: description: OK content: application/json: schema: title: CredentialCreationOptions type: object properties: attestation: type: string format: enum - direct - indirect - none authenticatorSelection: type: object properties: authenticatorAttachment: type: string format: enum - platform - cross-platform userVerification: type: string format: enum - required - preferred - discouraged requireResidentKey: type: boolean challenge: type: string description: The base64url encoded challenge that was sent to the client, as generated by assertionOptions. pubKeyCredParams: type: object properties: type: type: string alg: type: string rp: type: object description: RP credentials properties: name: type: string id: type: string username: type: string displayName: type: string user: type: object description: User object properties: id: type: string name: type: string displayName: type: string excludeCredentials: type: object properties: type: type: string id: type: string timeout: type: integer extensions: type: array items: type: string status: type: string errorMessage: type: string 403: $ref: '#/components/responses/AccessDenied' 500: $ref: '#/components/responses/InternalServerError' /jans-fido2/restv1/attestation/result: post: tags: - FIDO2 Attestation summary: FIDO2 attestation result. description: FIDO2 attestation result operationId: attestation-result requestBody: content: application/json: schema: title: AttestationOptions description: An object containing various options for the option creation type: object required: - id - type - response properties: id: type: string description: base64url encoded type: type: string enum: - public-key response: type: object required: - clientDataJSON - attestationObject properties: attestationObject: type: string description: base64url encoded clientDataJSON: type: object description: The base64url encoded clientDataJSON returned by the client required: - challenge - origin - type properties: type: type: string enum: - webauthn.create origin: type: string challenge: type: string tokenBinding: type: object required: - status properties: status: type: string id: type: string clientExtensionResults: type: array items: type: string responses: 200: description: OK content: application/json: schema: title: Fido2RegistrationData type: object properties: createdCredentials: type: object properties: createdDate: type: string format: date-time updatedDate: type: string format: date-time createdBy: type: string updatedBy: type: string username: type: string domain: type: string userId: type: string challenge: type: string attestationRequest: type: string attestationResponse: type: object properties: type: type: string enum: - public-key id: type: string response: type: object required: - attestationObject - clientDataJSON properties: attestationObject: type: string clientDataJSON: type: string clientExtensionResults: type: array items: type: string uncompressedECPoint: type: string publicKeyId: type: string type: type: string enum: - public-key status: type: string enum: - registered counter: type: integer attestationType: type: string signatureAlgorithm: type: integer applicationId: type: string authenticatorSelection: type: object properties: authenticatorAttachment: type: string format: enum - platform - cross-platform userVerification: type: string format: enum - required - preferred - discouraged requireResidentKey: type: boolean errorMessage: type: string status: type: string 403: $ref: '#/components/responses/AccessDenied' 500: $ref: '#/components/responses/InternalServerError' # --------------------------------------------------------------------------- # FIDO2 Metrics API (GitHub Issue #11922) # --------------------------------------------------------------------------- /jans-fido2/restv1/metrics/entries: get: tags: - FIDO2 Metrics summary: Get metrics entries description: Returns all raw metric entries between startTime and endTime (ISO 8601 UTC). Use for event-level detail or custom analysis. operationId: get-metrics-entries parameters: - name: startTime in: query required: true schema: type: string example: "2026-01-01T00:00:00" description: Start time (ISO 8601, UTC). - name: endTime in: query required: true schema: type: string example: "2026-01-01T23:59:59" description: End time (ISO 8601, UTC). responses: 200: description: List of metric entries. content: application/json: schema: type: array items: $ref: '#/components/schemas/MetricsEntry' 400: $ref: '#/components/responses/InvalidRequest' 403: $ref: '#/components/responses/AccessDenied' 500: $ref: '#/components/responses/InternalServerError' /jans-fido2/restv1/metrics/entries/user/{userId}: get: tags: - FIDO2 Metrics summary: Get metrics entries for a user description: Returns metric entries for a single user (by userId/inum) in the given time range. Unknown or invalid userId returns 200 with an empty array (consistent with other metrics endpoints); 404 is not used. operationId: get-metrics-entries-by-user parameters: - name: userId in: path required: true schema: type: string description: User internal ID (inum). - name: startTime in: query required: true schema: type: string description: Start time (ISO 8601, UTC). - name: endTime in: query required: true schema: type: string description: End time (ISO 8601, UTC). responses: 200: description: List of metric entries for the user. content: application/json: schema: type: array items: $ref: '#/components/schemas/MetricsEntry' 400: $ref: '#/components/responses/InvalidRequest' 403: $ref: '#/components/responses/AccessDenied' 500: $ref: '#/components/responses/InternalServerError' /jans-fido2/restv1/metrics/entries/operation/{operationType}: get: tags: - FIDO2 Metrics summary: Get metrics entries by operation type description: Returns metric entries filtered by operation type (REGISTRATION or AUTHENTICATION). operationId: get-metrics-entries-by-operation parameters: - name: operationType in: path required: true schema: type: string enum: - REGISTRATION - AUTHENTICATION description: Operation type filter. - name: startTime in: query required: true schema: type: string description: Start time (ISO 8601, UTC). - name: endTime in: query required: true schema: type: string description: End time (ISO 8601, UTC). responses: 200: description: List of metric entries for the operation type. content: application/json: schema: type: array items: $ref: '#/components/schemas/MetricsEntry' 400: $ref: '#/components/responses/InvalidRequest' 403: $ref: '#/components/responses/AccessDenied' 500: $ref: '#/components/responses/InternalServerError' /jans-fido2/restv1/metrics/aggregations/{aggregationType}: get: tags: - FIDO2 Metrics summary: Get aggregations description: Returns pre-computed aggregation records (one per period) that overlap the given time range. operationId: get-metrics-aggregations parameters: - name: aggregationType in: path required: true schema: type: string enum: - HOURLY - DAILY - WEEKLY - MONTHLY description: Aggregation granularity. - name: startTime in: query required: true schema: type: string description: Start time (ISO 8601, UTC). - name: endTime in: query required: true schema: type: string description: End time (ISO 8601, UTC). responses: 200: description: List of aggregation records. content: application/json: schema: type: array items: $ref: '#/components/schemas/MetricsAggregation' 400: $ref: '#/components/responses/InvalidRequest' 403: $ref: '#/components/responses/AccessDenied' 500: $ref: '#/components/responses/InternalServerError' /jans-fido2/restv1/metrics/aggregations/{aggregationType}/summary: get: tags: - FIDO2 Metrics summary: Get aggregation summary description: >- Returns a single summary over all aggregations in the time range (totals and average success rates). Reads stored aggregations, which are computed once for their period and never recalculated, so periods aggregated before 2.4.0 still carry the duration and device figures computed at the time. Read current latency from analytics/performance, which is computed live from entries. operationId: get-metrics-aggregation-summary parameters: - name: aggregationType in: path required: true schema: type: string enum: - HOURLY - DAILY - WEEKLY - MONTHLY - name: startTime in: query required: true schema: type: string description: Start time (ISO 8601, UTC). - name: endTime in: query required: true schema: type: string description: End time (ISO 8601, UTC). responses: 200: description: Summary statistics. content: application/json: schema: $ref: '#/components/schemas/MetricsAggregationSummary' 400: $ref: '#/components/responses/InvalidRequest' 403: $ref: '#/components/responses/AccessDenied' 500: $ref: '#/components/responses/InternalServerError' /jans-fido2/restv1/metrics/analytics/adoption: get: tags: - FIDO2 Metrics summary: Get adoption analytics description: Returns user adoption metrics (new users, returning users, adoption rate). operationId: get-metrics-analytics-adoption parameters: - name: startTime in: query required: true schema: type: string description: Start time (ISO 8601, UTC). - name: endTime in: query required: true schema: type: string description: End time (ISO 8601, UTC). responses: 200: description: Adoption analytics. content: application/json: schema: $ref: '#/components/schemas/MetricsAdoption' 400: $ref: '#/components/responses/InvalidRequest' 403: $ref: '#/components/responses/AccessDenied' 500: $ref: '#/components/responses/InternalServerError' /jans-fido2/restv1/metrics/analytics/performance: get: tags: - FIDO2 Metrics summary: Get performance analytics description: >- Returns performance statistics (average, min, max durations in milliseconds for registration and authentication). Durations cover only ceremonies that completed - SUCCESS or FAILURE. An abandoned ceremony's recorded duration is how long it stayed open before the sweep claimed it, which measures unfinishedRequestExpiration rather than user-perceived latency, so including it would make these figures track the configured window instead of the server. The keys for an operation type are absent when nothing completed in the range. operationId: get-metrics-analytics-performance parameters: - name: startTime in: query required: true schema: type: string description: Start time (ISO 8601, UTC). - name: endTime in: query required: true schema: type: string description: End time (ISO 8601, UTC). responses: 200: description: Performance analytics. content: application/json: schema: $ref: '#/components/schemas/MetricsPerformance' 400: $ref: '#/components/responses/InvalidRequest' 403: $ref: '#/components/responses/AccessDenied' 500: $ref: '#/components/responses/InternalServerError' /jans-fido2/restv1/metrics/analytics/devices: get: tags: - FIDO2 Metrics summary: Get device analytics description: >- Returns device analytics (device types, OS, browsers, authenticator types). Counts are per completed ceremony, not per recorded entry: a ceremony writes an ATTEMPT when it starts and a terminal entry when it resolves, so counting entries reported one sign-in more than once. Abandoned ceremonies do not appear - abandonment is recorded off a request thread, which has no device details to read. Still approximate in multi-node deployments, where a ceremony can be recorded more than once. operationId: get-metrics-analytics-devices parameters: - name: startTime in: query required: true schema: type: string description: Start time (ISO 8601, UTC). - name: endTime in: query required: true schema: type: string description: End time (ISO 8601, UTC). responses: 200: description: Device analytics. content: application/json: schema: $ref: '#/components/schemas/MetricsDeviceAnalytics' 400: $ref: '#/components/responses/InvalidRequest' 403: $ref: '#/components/responses/AccessDenied' 500: $ref: '#/components/responses/InternalServerError' /jans-fido2/restv1/metrics/analytics/errors: get: tags: - FIDO2 Metrics summary: Get error analytics description: >- Returns error analysis (categories, top errors, success/failure rates). Without operationType the tally covers registration and authentication together, which cannot distinguish a deployment with healthy sign-in and poor enrolment from the reverse - pass operationType to report one ceremony at a time. operationId: get-metrics-analytics-errors parameters: - name: startTime in: query required: true schema: type: string description: Start time (ISO 8601, UTC). - name: endTime in: query required: true schema: type: string description: End time (ISO 8601, UTC). - name: operationType in: query required: false schema: type: string enum: [REGISTRATION, AUTHENTICATION] description: >- Report this ceremony alone. Omit to report both together, which is the long-standing behaviour of this endpoint. responses: 200: description: Error analytics. content: application/json: schema: $ref: '#/components/schemas/MetricsErrorAnalytics' 400: $ref: '#/components/responses/InvalidRequest' 403: $ref: '#/components/responses/AccessDenied' 500: $ref: '#/components/responses/InternalServerError' /jans-fido2/restv1/metrics/analytics/attestation-rejections: get: tags: - FIDO2 Metrics summary: Get attestation rejection analytics description: >- Returns attestation rejections broken down by trust diagnostic code. An unknown AAGUID, an authenticator blocked by an MDS status report and an untrusted root certificate are otherwise indistinguishable from each other, and from any other registration failure. Reads the same metrics store as the error analytics endpoint. operationId: get-metrics-analytics-attestation-rejections parameters: - name: startTime in: query required: true schema: type: string description: Start time (ISO 8601, UTC). - name: endTime in: query required: true schema: type: string description: End time (ISO 8601, UTC). responses: 200: description: Attestation rejection analytics. content: application/json: schema: $ref: '#/components/schemas/AttestationRejectionAnalytics' 400: $ref: '#/components/responses/InvalidRequest' 403: $ref: '#/components/responses/AccessDenied' 500: $ref: '#/components/responses/InternalServerError' /jans-fido2/restv1/metrics/analytics/trends/{aggregationType}: get: tags: - FIDO2 Metrics summary: Get trend analysis description: >- Returns trend data over time for the chosen aggregation granularity, with insights (e.g. direction, growth rate). Built from stored aggregations rather than recomputed, so periods aggregated before 2.4.0 still carry the duration and device figures computed at the time and should be read as legacy data. operationId: get-metrics-analytics-trends parameters: - name: aggregationType in: path required: true schema: type: string enum: - HOURLY - DAILY - WEEKLY - MONTHLY - name: startTime in: query required: true schema: type: string description: Start time (ISO 8601, UTC). - name: endTime in: query required: true schema: type: string description: End time (ISO 8601, UTC). responses: 200: description: Trend analysis. content: application/json: schema: $ref: '#/components/schemas/MetricsTrends' 400: $ref: '#/components/responses/InvalidRequest' 403: $ref: '#/components/responses/AccessDenied' 500: $ref: '#/components/responses/InternalServerError' /jans-fido2/restv1/metrics/analytics/comparison/{aggregationType}: get: tags: - FIDO2 Metrics summary: Get period-over-period comparison description: Compares the current period with previous periods (e.g. this month vs last). The time range is calculated internally from the aligned current period boundary (UTC) and the number of periods; API consumers do not provide startTime or endTime. Optional query parameter periods (2–12, default 2) specifies how many consecutive periods to compare. operationId: get-metrics-analytics-comparison parameters: - name: aggregationType in: path required: true schema: type: string enum: - HOURLY - DAILY - WEEKLY - MONTHLY - name: periods in: query required: false schema: type: integer minimum: 2 maximum: 12 default: 2 description: Number of consecutive periods to compare. responses: 200: description: Period comparison data. content: application/json: schema: $ref: '#/components/schemas/MetricsPeriodComparison' 400: $ref: '#/components/responses/InvalidRequest' 403: $ref: '#/components/responses/AccessDenied' 500: $ref: '#/components/responses/InternalServerError' /jans-fido2/restv1/metrics/config: get: tags: - FIDO2 Metrics summary: Get metrics configuration description: Returns current metrics configuration (enabled, retention, device info, error categorization, supported aggregation types). operationId: get-metrics-config responses: 200: description: Metrics configuration. content: application/json: schema: $ref: '#/components/schemas/MetricsConfig' 403: $ref: '#/components/responses/AccessDenied' 500: $ref: '#/components/responses/InternalServerError' /jans-fido2/restv1/metrics/health: get: tags: - FIDO2 Metrics summary: Metrics health check description: Returns health status. HTTP 200 when UP, 503 when DOWN (e.g. database unavailable). operationId: get-metrics-health responses: 200: description: Service is UP. content: application/json: schema: $ref: '#/components/schemas/MetricsHealth' 503: description: Service is DOWN (e.g. database unavailable). content: application/json: schema: $ref: '#/components/schemas/MetricsHealth' 500: $ref: '#/components/responses/InternalServerError' /jans-fido2/restv1/trust/attestation/config: get: tags: - FIDO2 Trust summary: Get effective attestation configuration description: >- Returns the attestation policy the server is actually enforcing, so an administrator can see whether a strict mode is the reason authenticators are being rejected. Read-only. operationId: get-trust-attestation-config responses: 200: description: Effective attestation configuration. content: application/json: schema: $ref: '#/components/schemas/AttestationTrustConfig' 403: $ref: '#/components/responses/AccessDenied' 500: $ref: '#/components/responses/InternalServerError' /jans-fido2/restv1/trust/mds/health: get: tags: - FIDO2 Trust summary: Get FIDO Metadata Service health description: >- Returns the state of the metadata used for attestation validation: how many entries are loaded, whether the loaded blob is still valid, and how the last refresh went. A stale or failed MDS load is a common cause of a previously valid authenticator suddenly being rejected. Read-only — this endpoint never triggers a metadata download or reads the document store. operationId: get-trust-mds-health responses: 200: description: >- MDS health. Returned for status UP and for status DISABLED — a metadata service switched off by configuration is a deliberate choice, not an outage, and must not page a monitor wired to this endpoint. content: application/json: schema: $ref: '#/components/schemas/MdsHealth' 503: description: >- Status is DOWN — no metadata is loaded, or the loaded blob has reached its nextUpdate (today or earlier) and a refresh is overdue. The diagnostic body is returned with the 503 as well. content: application/json: schema: $ref: '#/components/schemas/MdsHealth' 403: $ref: '#/components/responses/AccessDenied' 500: $ref: '#/components/responses/InternalServerError' components: responses: Found: #302 - FOUND description: Resource Found. content: {} InvalidRequest: #400 - BAD_REQUEST description: Invalid parameters are provided to endpoint. content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' Unauthorized: #401 - UNAUTHORIZED description: Unauthorized access request. content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' AccessDenied: #403 - FORBIDDEN description: Invalid details provided hence access denied. content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' NotFound: #404 - NOT_FOUND description: Resource Not Found. content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' NotAcceptable: #406 - NOT_ACCEPTABLE description: Request Not Acceptable. content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' InternalServerError: #500 - INTERNAL_SERVER_ERROR description: Internal error occured. Please check log file for details. content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' schemas: ErrorResponse: required: - error - error_description type: object properties: error: type: string error_description: type: string details: type: string # FIDO2 Metrics API schemas MetricsEntry: type: object description: A single raw metric entry (one registration or authentication event). properties: id: type: string description: Unique identifier for the entry. timestamp: type: integer format: int64 description: Event time in milliseconds since epoch (UTC). userId: type: string description: User internal ID (inum). username: type: string description: Human-readable username at time of operation; use userId for stable tracking. operationType: type: string enum: - REGISTRATION - AUTHENTICATION - FALLBACK description: REGISTRATION (passkey enrollment), AUTHENTICATION (sign-in), or FALLBACK (alternative method). status: type: string enum: - SUCCESS - FAILURE - ATTEMPT - ABANDONED description: ATTEMPT (started), SUCCESS (completed), FAILURE (completed with error), or ABANDONED (authentication ceremony started but never completed). ABANDONED is not a completion and is excluded from the attempt total that failures are derived from. durationMs: type: integer description: Operation duration in milliseconds. authenticatorType: type: string description: e.g. cross-platform, platform, security-key. nodeId: type: string description: Cluster node identifier (when in cluster). ipAddress: type: string description: Client IP address (when available from request headers). Useful for geo-analysis or security. userAgent: type: string description: Full browser user-agent string; used to derive deviceInfo. deviceInfo: type: object description: Parsed device details (browser, os, deviceType). Present when deviceInfoCollection is enabled. errorReason: type: string description: Human-readable error message. Present only when status is FAILURE. errorCategory: type: string description: Categorized error type (e.g. USER_CANCELLED, TIMEOUT, INVALID_CREDENTIAL). Present only when status is FAILURE. sessionId: type: string description: Session identifier linking this operation to a user session. applicationType: type: string description: Application or relying party identifier (when multiple apps share the FIDO2 server). MetricsAggregation: type: object description: Pre-computed aggregation for one period (e.g. one hour or one day). properties: id: type: string description: e.g. HOURLY_2026-01-01-12 or WEEKLY_2026-W07. aggregationType: type: string enum: - HOURLY - DAILY - WEEKLY - MONTHLY startTime: type: integer format: int64 description: Period start in milliseconds since epoch (UTC), inclusive. endTime: type: integer format: int64 description: Period end in milliseconds since epoch (UTC), exclusive. period: type: string description: Period identifier (e.g. 2026-01-01-12 for hour, 2026-W07 for week). uniqueUsers: type: integer description: Count of distinct users with activity in this period. registrationAttempts: type: integer description: Total registration operations (SUCCESS or FAILURE) in this period. registrationSuccesses: type: integer description: Successful registrations in this period. registrationFailures: type: integer description: Failed registrations in this period. registrationSuccessRate: type: number format: double description: registrationSuccesses / registrationAttempts (0.0–1.0). registrationAvgDuration: type: number description: Milliseconds. authenticationAttempts: type: integer description: Total authentication operations (SUCCESS or FAILURE) in this period. authenticationSuccesses: type: integer description: Successful authentications in this period. authenticationFailures: type: integer description: Failed authentications in this period. authenticationSuccessRate: type: number description: authenticationSuccesses / authenticationAttempts (0.0–1.0). authenticationAvgDuration: type: number description: Milliseconds. deviceTypes: type: object additionalProperties: type: integer description: Counts by device type (e.g. platform, cross-platform). errorCounts: type: object additionalProperties: type: integer description: Counts by error category (e.g. USER_CANCELLED, TIMEOUT). MetricsAggregationSummary: type: object description: Summary over all aggregations in a time range. properties: totalRegistrations: type: integer description: Total registration operations across all periods in the range. totalAuthentications: type: integer description: Total authentication operations across all periods in the range. totalOperations: type: integer description: Sum of totalRegistrations and totalAuthentications. totalFallbacks: type: integer description: Count of fallback events (user chose alternative to passkey) in the range. avgRegistrationSuccessRate: type: number description: Average of registration success rates across periods (0.0–1.0). avgAuthenticationSuccessRate: type: number description: Average of authentication success rates across periods (0.0–1.0). MetricsAdoption: type: object description: User adoption metrics (new users, returning users, adoption rate) for the given time range. properties: newUsers: type: integer returningUsers: type: integer totalUniqueUsers: type: integer adoptionRate: type: number description: newUsers / totalUniqueUsers (0.0–1.0). MetricsPerformance: type: object description: Performance statistics (avg/min/max durations in milliseconds for registration and authentication). properties: registrationAvgDuration: type: number description: Average registration duration (ms). registrationMinDuration: type: integer description: Minimum registration duration (ms). registrationMaxDuration: type: integer description: Maximum registration duration (ms). authenticationAvgDuration: type: number description: Average authentication duration (ms). authenticationMinDuration: type: integer description: Minimum authentication duration (ms). authenticationMaxDuration: type: integer description: Maximum authentication duration (ms). MetricsDeviceAnalytics: type: object description: Device analytics (device types, OS, browsers, authenticator types). properties: deviceTypes: type: object additionalProperties: type: integer description: Counts by device type (e.g. desktop, mobile). authenticatorTypes: type: object additionalProperties: type: integer description: Counts by authenticator type (platform, cross-platform). browsers: type: object additionalProperties: type: integer description: Counts by browser. operatingSystems: type: object additionalProperties: type: integer description: Counts by operating system. MetricsErrorAnalytics: type: object description: Error analysis (categories, top errors, success/failure rates). properties: errorCategories: type: object additionalProperties: type: integer description: Count of errors by category. topErrors: type: object additionalProperties: type: integer description: Count of errors by message. successRate: type: number nullable: true description: Ratio of started operations that succeeded. Based on ATTEMPT count as denominator, and reported as observed, so it can exceed 1.0 when completions in the range belong to starts outside it. Null when nothing was recorded. Where no ATTEMPT entries exist at all it is the share of completed ceremonies that succeeded instead — see rateNote. failureRate: type: number nullable: true description: Ratio of started operations that failed. Same denominator and same caveats as successRate. completionRate: type: number nullable: true description: Ratio of started operations that completed (success or failure), 0.0–1.0. Capped at 1.0 when completions outnumber recorded starts, and null when no starts were recorded at all, since it then has no denominator — see rateNote. dropOffRate: type: number nullable: true description: Ratio of started operations that did not complete (user dropped off). Equals 1 - completionRate (0.0–1.0). Inferred as a residual, so it also absorbs ceremonies still in flight at the edge of the query window, and is null when there is no residual to infer it from — see rateNote. abandonedOperations: type: integer description: Count of authentication ceremonies observed to have lapsed without ever being completed. Unlike dropOffRate this is counted from ceremonies actually relabelled as abandoned, not inferred. Approximate in multi-node deployments, where a ceremony may be counted more than once. abandonmentRate: type: number nullable: true description: Ratio of started operations observed to have been abandoned (0.0–1.0). Based on ATTEMPT count as denominator. Reported alongside dropOffRate, not instead of it. Null when no starts were recorded — see rateNote. rateNote: type: string description: Present only when a rate in this response is null, capped, or measured against a different denominator, and explains which and why. An unknown rate must not be rendered as a zero. MetricsTrends: type: object description: Trend analysis over time with data points, growth rate, direction, and insights. properties: dataPoints: type: array description: One data point per aggregation period (timestamp, period, metrics). growthRate: type: number description: Overall growth rate (e.g. 0.15 = 15% growth). trendDirection: type: string description: INCREASING, DECREASING, or STABLE. insights: type: object description: Peak period, peak operations, average operations. MetricsPeriodComparison: type: object description: Period-over-period comparison (current vs previous period metrics and percentage change). properties: currentPeriod: type: object description: Summary for the most recent period(s). previousPeriod: type: object description: Summary for the preceding period(s). comparison: type: object description: Percentage changes between periods (e.g. totalOperationsChange). MetricsConfig: type: object description: Current metrics configuration as seen by the server. properties: metricsEnabled: type: boolean description: Whether metrics collection is enabled. aggregationEnabled: type: boolean description: Whether automatic aggregation jobs are enabled. retentionDays: type: integer description: Number of days metrics data is retained before cleanup. deviceInfoCollection: type: boolean description: Whether device info (browser, OS) is collected. errorCategorization: type: boolean description: Whether errors are categorized for analytics. performanceMetrics: type: boolean description: Whether durations are tracked. supportedAggregationTypes: type: array items: type: string example: ["HOURLY", "DAILY", "WEEKLY", "MONTHLY"] description: List of available aggregation granularities. MetricsHealth: type: object description: Health status of the metrics service (200 = UP, 503 = DOWN). properties: status: type: string enum: - UP - DOWN description: Overall health; UP returns 200, DOWN returns 503. metricsEnabled: type: boolean description: Whether metrics collection is enabled in configuration. aggregationEnabled: type: boolean description: Whether automatic aggregation is enabled. timestamp: type: string description: Current server time (ISO format, UTC). serviceAvailable: type: boolean description: True if metrics backend (e.g. DB) is reachable. AttestationRejectionAnalytics: type: object description: >- Attestation rejections in a time range, broken down by cause. A rejection is a registration failure recorded with the ATTESTATION_TRUST error category. properties: totalRejections: type: integer example: 37 description: Attestation rejections recorded in the range. registrationAttempts: type: integer example: 412 description: Registration attempts recorded in the range — the denominator of rejectionRate. rejectionRate: type: number format: double nullable: true example: 0.0898 description: >- Rejections as a proportion of registration attempts in the range. Null when no attempts were recorded, since a rate cannot be computed without a denominator — see rejectionRateNote. Capped at 1.0 when rejections belong to attempts recorded before the range started. rejectionRateNote: type: string description: >- Present only when the rate is null or capped, explaining why. Absent when the rate is exact. reasonCodes: type: object additionalProperties: type: integer example: JFS_AAGUID_NOT_IN_MDS: 21 JFS_ROOT_CERT_NOT_TRUSTED: 5 description: >- Count per diagnostic code. The codes a rejection can currently be reported under are JFS_AAGUID_NOT_IN_MDS, JFS_MDS_UNAVAILABLE, JFS_ATTESTATION_FORMAT_NOT_PERMITTED, JFS_ROOT_CERT_NOT_TRUSTED, JFS_APPLE_ROOT_CA_MISSING and JFS_AUTHENTICATOR_STATUS_UNACCEPTABLE. JFS_MDS_METADATA_EXPIRED is reserved and is not emitted yet: an expired blob is discarded when it is loaded, so expiry surfaces as JFS_AAGUID_NOT_IN_MDS. topRejectedAaguids: type: object additionalProperties: type: integer example: d8522d9f-575b-4866-88a9-ba99fa02f35b: 14 description: >- Count per AAGUID. Rejections that are not tied to an authenticator model — an attestation format the mode does not permit, for instance — are counted in reasonCodes only. AttestationTrustConfig: type: object description: Effective attestation policy. Read-only view of the FIDO2 configuration; changing it is out of scope for this endpoint. properties: attestationMode: type: string example: monitor description: >- The configured attestation mode, reported verbatim (default "monitor"). The supported values are "disabled", "monitor" and "enforced", but this field is deliberately not constrained to them: an unsupported value is returned as-is rather than normalised, so a typo is visible — see attestationModeRecognized. attestationModeRecognized: type: boolean description: >- Whether the configured value matches one of the supported modes. When false the server falls back to lenient behaviour, which is otherwise invisible to an administrator. unattestedAuthenticatorsAllowed: type: boolean description: >- Whether an authenticator that fails attestation validation is still accepted. True for every mode except "enforced" — only that mode applies the stricter MDS trust rules, so the default "monitor" still accepts such an authenticator. enterpriseAttestation: type: boolean description: Whether enterprise attestation is enabled. metadataServiceDisabled: type: boolean description: Whether MDS download and validation are switched off. When true, attestation cannot be validated against FIDO metadata. appleRootCaPresent: type: boolean description: >- Whether the Apple WebAuthn root CA certificate was loaded at startup. When false, Apple anonymous attestation cannot be validated. enabledFidoAlgorithms: type: array items: type: string example: ["RS256", "ES256"] description: Signature algorithms the server accepts. hints: type: array items: type: string example: ["security-key", "client-device", "hybrid"] description: Configured RP hints. MdsHealth: type: object description: >- State of the FIDO Metadata Service data used for attestation validation. Read-only; assembled entirely from in-memory state. properties: status: type: string enum: [UP, DOWN, DISABLED] description: >- UP — metadata is loaded and its nextUpdate is still in the future. DOWN — no entries are loaded, or the loaded blob has reached its nextUpdate (today or earlier) and a refresh is overdue; returned with HTTP 503. DISABLED — the metadata service is switched off by configuration; returned with HTTP 200, since that is a deliberate choice rather than an outage. Note that a failed refresh on its own is not DOWN: while the cached blob is still valid, attestation validation works normally. Alert on lastRefreshError for early warning that the metadata is heading towards expiry. metadataServiceDisabled: type: boolean description: Whether MDS download and validation are switched off by configuration. tocEntryCount: type: integer example: 1284 description: >- Authenticator metadata entries currently loaded in memory. Zero means attestation has no metadata to validate against. nextUpdate: type: string format: date example: "2026-08-15" description: >- The nextUpdate declared by the loaded TOC blob. Absent when no blob has been parsed since startup. blobExpired: type: boolean description: >- True when no blob is loaded, or its nextUpdate is today or earlier — i.e. a re-download is due. This is the same rule the server itself applies when deciding whether to download. Note that a blob is only discarded once its nextUpdate has actually passed, so on the day itself the blob is still in use while a refresh is already overdue. lastSuccessfulRefresh: type: string format: date-time example: "2026-08-01T04:15:22Z" description: >- When metadata was last downloaded and parsed successfully, as an ISO-8601 date-time with a UTC offset. Absent when no refresh has succeeded since startup. lastRefreshError: type: string example: "MDS TOC download failed: Connection timed out" description: >- Why the most recent refresh failed; absent when the last refresh succeeded. Reports the first failure of the attempt, which is the root cause — a failed download is followed by a fallback to the cached blob that tends to fail too. metadataServers: type: array items: $ref: '#/components/schemas/MetadataServerStatus' description: The configured metadata endpoints. timestamp: type: string format: date-time example: "2026-08-07T09:31:04.118Z" description: >- When this health snapshot was taken, as an ISO-8601 date-time with a UTC offset. MetadataServerStatus: type: object description: A configured MDS endpoint. properties: url: type: string example: "https://mds.fidoalliance.org/" description: The configured metadata endpoint URL. rootCertConfigured: type: boolean description: >- Whether a per-endpoint trust anchor (MetadataServer.rootCert) is configured. Reported as a presence flag only — the certificate itself never leaves the server.