{
  "openapi": "3.1.0",
  "info": {
    "title": "Noxtica public API",
    "version": "0.4.0",
    "summary": "Every public operation and webhook of the Noxtica server APIs in one document.",
    "description": "Noxtica public API, OpenAPI release v0.4.0 (2026-10-27). The identity verification, Pulse and MCP operations are served from their own hosts: every path item carries its `servers`. Reference: https://noxtica.com/docs/api/reference/. Each API is also published on its own at https://noxtica.com/docs/api/openapi/<api>.json.",
    "contact": {
      "name": "Noxtica documentation",
      "url": "https://noxtica.com/docs/api/"
    }
  },
  "servers": [
    {
      "url": "https://collect.noxtica.com",
      "description": "Production",
      "x-noxtica-key-prefix": "sk_prod_"
    }
  ],
  "tags": [
    {
      "name": "KYC Verification",
      "description": "Core single-call identity verification.",
      "externalDocs": {
        "description": "Identity verification API: reference page",
        "url": "https://noxtica.com/docs/api/reference/kyc/"
      }
    },
    {
      "name": "KYC Cross-Validation",
      "description": "Self-uploaded supporting-document cross-matches against an already-verified identity.",
      "externalDocs": {
        "description": "Identity verification API: reference page",
        "url": "https://noxtica.com/docs/api/reference/kyc/"
      }
    },
    {
      "name": "KYC Batch",
      "description": "CSV/JSON bulk verification submission and result retrieval.",
      "externalDocs": {
        "description": "Identity verification API: reference page",
        "url": "https://noxtica.com/docs/api/reference/kyc/"
      }
    },
    {
      "name": "KYC Reverify",
      "description": "Metered re-check of an already-established identity without re-collecting evidence.",
      "externalDocs": {
        "description": "Identity verification API: reference page",
        "url": "https://noxtica.com/docs/api/reference/kyc/"
      }
    },
    {
      "name": "KYC Evidence",
      "description": "Ciphertext-only raw evidence (document/selfie image) storage, server-to-server.",
      "externalDocs": {
        "description": "Identity verification API: reference page",
        "url": "https://noxtica.com/docs/api/reference/kyc/"
      }
    },
    {
      "name": "KYC Hosted Sessions",
      "description": "Noxtica-hosted verification-page session lifecycle (S2S mint/status + browser-facing session routes).",
      "externalDocs": {
        "description": "Identity verification API: reference page",
        "url": "https://noxtica.com/docs/api/reference/kyc/"
      }
    },
    {
      "name": "KYC Compliance",
      "description": "Right-to-erasure and mobile-activation orchestration.",
      "externalDocs": {
        "description": "Identity verification API: reference page",
        "url": "https://noxtica.com/docs/api/reference/kyc/"
      }
    },
    {
      "name": "KYC Webhooks",
      "description": "Signed events Noxtica POSTs to your registered endpoints (documented in the top-level `webhooks` section; the delivery rules are in \"Webhooks (KYC)\" above).",
      "externalDocs": {
        "description": "Identity verification API: reference page",
        "url": "https://noxtica.com/docs/api/reference/kyc/"
      }
    },
    {
      "name": "KYM",
      "description": "Merchant/transaction monitoring signal intake and hosted onboarding sessions.",
      "externalDocs": {
        "description": "Identity verification API: reference page",
        "url": "https://noxtica.com/docs/api/reference/kyc/"
      }
    },
    {
      "name": "MCP Server",
      "description": "The MCP JSON-RPC 2.0 endpoint.",
      "externalDocs": {
        "description": "MCP server: reference page",
        "url": "https://noxtica.com/docs/api/reference/mcp/"
      }
    },
    {
      "name": "Tenant",
      "description": "Server-to-server tenant plane (`/pulse/v1/tenant/*`) — subject status, response decisions, link codes and links, called from the tenant's own back end with a tenant API key.",
      "externalDocs": {
        "description": "Pulse tenant API: reference page",
        "url": "https://noxtica.com/docs/api/reference/pulse/"
      }
    },
    {
      "name": "Devices",
      "description": "Device fingerprint lookup and listing.",
      "externalDocs": {
        "description": "Device intelligence API: reference page",
        "url": "https://noxtica.com/docs/api/reference/device/"
      }
    },
    {
      "name": "Events & Visits",
      "description": "Raw event and visit reads.",
      "externalDocs": {
        "description": "Device intelligence API: reference page",
        "url": "https://noxtica.com/docs/api/reference/device/"
      }
    },
    {
      "name": "Exports",
      "description": "Bulk export of fingerprints/events/visits/scored-events, plus the emerging-threats feed.",
      "externalDocs": {
        "description": "Device intelligence API: reference page",
        "url": "https://noxtica.com/docs/api/reference/device/"
      }
    },
    {
      "name": "APM Observability",
      "description": "Project and environment inventory, bounded APM queries, asynchronous exports and privacy-request status. Customer and general capture are not yet available; an approved proof-of-concept is limited to synthetic, no-personal-data telemetry.",
      "externalDocs": {
        "description": "Observability query API: reference page",
        "url": "https://noxtica.com/docs/api/reference/observability/"
      }
    },
    {
      "name": "APM Ingest",
      "description": "OTLP/HTTP trace, metric, log and profile ingestion, plus deployment markers. Write-only telemetry, distinct from the read-only \"APM Observability\" tag. Authenticated with an `sk_apm_` ingestion key (never a server API key) and served from the ingestion hosts, and also from the collector hosts.",
      "externalDocs": {
        "description": "Telemetry ingestion API: reference page",
        "url": "https://noxtica.com/docs/api/reference/ingest/"
      }
    },
    {
      "name": "Sealed Results",
      "description": "Cryptographically sealed high-assurance result retrieval.",
      "externalDocs": {
        "description": "Device intelligence API: reference page",
        "url": "https://noxtica.com/docs/api/reference/device/"
      }
    },
    {
      "name": "Labels",
      "description": "Ground-truth fraud/legitimate labeling.",
      "externalDocs": {
        "description": "Device intelligence API: reference page",
        "url": "https://noxtica.com/docs/api/reference/device/"
      }
    },
    {
      "name": "Generator",
      "description": "Synthetic fingerprint generation for testing/load.",
      "externalDocs": {
        "description": "Device intelligence API: reference page",
        "url": "https://noxtica.com/docs/api/reference/device/"
      }
    },
    {
      "name": "Reputation",
      "description": "Email, website and phone reputation checks.",
      "externalDocs": {
        "description": "Risk scoring and agent trust API: reference page",
        "url": "https://noxtica.com/docs/api/reference/score/"
      }
    },
    {
      "name": "Crawl Vouchers",
      "description": "Signed crawler-access vouchers.",
      "externalDocs": {
        "description": "Risk scoring and agent trust API: reference page",
        "url": "https://noxtica.com/docs/api/reference/score/"
      }
    },
    {
      "name": "Behavioral Baseline",
      "description": "Behavioral-subject baseline read and erase (not enabled by default).",
      "externalDocs": {
        "description": "Device intelligence API: reference page",
        "url": "https://noxtica.com/docs/api/reference/device/"
      }
    },
    {
      "name": "Agent Trust",
      "description": "Web Bot Auth (RFC 9421) agent verification and signed Agent Passports.",
      "externalDocs": {
        "description": "Risk scoring and agent trust API: reference page",
        "url": "https://noxtica.com/docs/api/reference/score/"
      }
    },
    {
      "name": "IP & Risk Scoring",
      "description": "Standalone IP reputation and composite risk scoring.",
      "externalDocs": {
        "description": "Risk scoring and agent trust API: reference page",
        "url": "https://noxtica.com/docs/api/reference/score/"
      }
    },
    {
      "name": "Protected Actions",
      "description": "Server-side redemption of the `requestId` a browser obtains for a declared protected action (login, signup, checkout, ...).",
      "externalDocs": {
        "description": "Protected actions API: reference page",
        "url": "https://noxtica.com/docs/api/reference/protected-actions/"
      }
    },
    {
      "name": "Device Attestation",
      "description": "Mobile platform attestation (Play Integrity / App Attest) and PoW/integrity verification.",
      "externalDocs": {
        "description": "Mobile and device identity API: reference page",
        "url": "https://noxtica.com/docs/api/reference/mobile/"
      }
    },
    {
      "name": "Web/App Integrity",
      "description": "Web/app integrity verification distinct from device attestation.",
      "externalDocs": {
        "description": "Mobile and device identity API: reference page",
        "url": "https://noxtica.com/docs/api/reference/mobile/"
      }
    },
    {
      "name": "Mobile App Config",
      "description": "Mobile app runtime configuration delivery.",
      "externalDocs": {
        "description": "Mobile and device identity API: reference page",
        "url": "https://noxtica.com/docs/api/reference/mobile/"
      }
    },
    {
      "name": "Passkey",
      "description": "WebAuthn passkey challenge, register and assert (not enabled by default).",
      "externalDocs": {
        "description": "Mobile and device identity API: reference page",
        "url": "https://noxtica.com/docs/api/reference/mobile/"
      }
    },
    {
      "name": "Device Handoff",
      "description": "Cross-device session handoff mint and consume (not enabled by default).",
      "externalDocs": {
        "description": "Mobile and device identity API: reference page",
        "url": "https://noxtica.com/docs/api/reference/mobile/"
      }
    },
    {
      "name": "Device Delegation",
      "description": "Subject-scoped device delegation lifecycle (write:identity, not enabled by default).",
      "externalDocs": {
        "description": "Mobile and device identity API: reference page",
        "url": "https://noxtica.com/docs/api/reference/mobile/"
      }
    },
    {
      "name": "Account Recovery",
      "description": "Account-recovery case and appeal lifecycle (write:identity, not enabled by default).",
      "externalDocs": {
        "description": "Mobile and device identity API: reference page",
        "url": "https://noxtica.com/docs/api/reference/mobile/"
      }
    },
    {
      "name": "Wallet Status",
      "description": "Device-bound wallet status and suspend operations (write:identity, not enabled by default).",
      "externalDocs": {
        "description": "Mobile and device identity API: reference page",
        "url": "https://noxtica.com/docs/api/reference/mobile/"
      }
    },
    {
      "name": "Offline Capture",
      "description": "Offline-first nonce pool and capture-bundle intake.",
      "externalDocs": {
        "description": "Mobile and device identity API: reference page",
        "url": "https://noxtica.com/docs/api/reference/mobile/"
      }
    },
    {
      "name": "Coding Agent",
      "description": "Read-only access for coding agents to your organisation's recent errors, traces and signals, authenticated with a `cak_` key on the ingestion hosts.",
      "externalDocs": {
        "description": "Observability query API: reference page",
        "url": "https://noxtica.com/docs/api/reference/observability/"
      }
    },
    {
      "name": "Health and Keys",
      "description": "The unauthenticated collector health probe and the public signing-key documents used to verify signed envelopes offline.",
      "externalDocs": {
        "description": "Health and public key endpoints: reference page",
        "url": "https://noxtica.com/docs/api/reference/status/"
      }
    },
    {
      "name": "Verdict Webhooks",
      "description": "Signed events Noxtica POSTs to your registered endpoints when a submission is scored, flagged, or linked to an agent (documented in the top-level `webhooks` section).",
      "externalDocs": {
        "description": "Device intelligence API: reference page",
        "url": "https://noxtica.com/docs/api/reference/device/"
      }
    }
  ],
  "paths": {
    "/v1/kyc/verify": {
      "post": {
        "operationId": "kycVerify",
        "tags": [
          "KYC Verification"
        ],
        "summary": "Verify an identity",
        "description": "Two branches, selected by the body's `action` field (`verify` is the implicit default when `action` is omitted — every pre-existing caller is unaffected):\n\n`action:'verify'` admits, screens, policy-enforces, and finalizes a single identity verification against the tenant's configured provider. The admission → spend-reservation → provider-call → finalize pipeline is shared byte-for-byte with the hosted-session submit path (`POST /v1/kyc/session-submit`) and the batch processor — there is exactly one verify pipeline in this system. It requires a `nonce` obtained from a prior `action:'mint'` call to the SAME endpoint (the only route that legitimately issues one) or a valid hosted-session-derived nonce.\n\n`action:'mint'` issues that admission nonce: a fresh, tenant-scoped, single-use nonce bound in KV to the calling tenant (TTL 300s). It is the ONLY way a server-to-server caller can obtain a nonce a subsequent `action:'verify'` call will accept — without it, `evidence-handle`/`cross-match`/`reverify` are unreachable S2S, since every one of those requires an admitted `verificationId` a real `verify` call produces. Mint runs the SAME auth/module-gate/legal-basis preflight as verify, but NEVER meters, NEVER reserves spend, and makes ZERO provider calls.",
        "security": [
          {
            "ApiKeyAuth": [
              "write:identity"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKeyRequired"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/KycVerifyRequest"
              },
              "examples": {
                "mint": {
                  "summary": "action:'mint' — issue a fresh admission nonce",
                  "value": {
                    "action": "mint"
                  }
                },
                "verify": {
                  "summary": "action:'verify' (default) — spend a previously minted nonce",
                  "value": {
                    "nonce": "nonce_5f3a8c1e2d4b6f709182a3b4c5d6e7f8",
                    "id_type": "passport",
                    "purpose": "liveness_check",
                    "payload": {
                      "scenario": "verified"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "`action:'mint'`: a freshly minted admission nonce (`KycVerifyMintResponse`) — zero provider calls, zero spend. `action:'verify'`: a resolved verify attempt (verified, unverified, or an infra `error` verdict), a nonce-replay of a prior identical request, or an admission-level refusal (`KycVerifyResponse`). `verdict:'error'` and every nonce-fault outcome (e.g. `nonce_unknown` for a never-minted or wrong-tenant nonce, `nonce_expired` for one past its 300s TTL) are HTTP 200 by design (FR-6) — a happy-path 5xx is never returned for `action:'verify'`; mint's own KV-write fault is the one 5xx exception (503, below).",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/KycVerifyMintResponse"
                    },
                    {
                      "$ref": "#/components/schemas/KycVerifyResponse"
                    }
                  ]
                },
                "examples": {
                  "mint": {
                    "summary": "A freshly minted nonce",
                    "value": {
                      "ok": true,
                      "nonce": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                      "ttlSeconds": 300
                    }
                  },
                  "verified": {
                    "summary": "A verified identity",
                    "value": {
                      "ok": true,
                      "verdict": "verified",
                      "verificationLevel": "verified",
                      "reasonCodes": [
                        "name_match",
                        "document_authentic"
                      ],
                      "verificationId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                      "requestId": "req-test"
                    }
                  },
                  "nonceUnknown": {
                    "summary": "action:'verify' with a never-minted (or foreign-tenant) nonce — terminal unverified, zero provider calls",
                    "value": {
                      "ok": true,
                      "verdict": "unverified",
                      "verificationLevel": "unverified",
                      "reasonCodes": [
                        "nonce_unknown"
                      ],
                      "verificationId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                      "requestId": "req-test"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/InvalidApiKey"
          },
          "402": {
            "description": "`spend_cap_reached` — `action:'verify'` only. The request was admitted, but no active pricing is configured for your organisation, so the verification was refused before any provider call. Never returned for `action:'mint'` (a mint never reserves spend). See the `403` response for the other refusal of this kind.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "spend_cap_reached"
                      ]
                    },
                    "code": {
                      "type": "string",
                      "enum": [
                        "spend_cap_reached"
                      ]
                    },
                    "requestId": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "error": "spend_cap_reached",
                  "code": "spend_cap_reached",
                  "requestId": "req-test"
                }
              }
            }
          },
          "403": {
            "description": "Either the presented key lacks the required scope (`ScopeForbidden` shape), or — `action:'verify'` only — `tenant_inactive`: your organisation became inactive between nonce admission and the spend check, so the verification was refused. No provider call is made either way.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "type": "object",
                      "additionalProperties": false,
                      "properties": {
                        "error": {
                          "type": "string",
                          "example": "API key does not have write:identity scope"
                        },
                        "requestId": {
                          "type": "string"
                        }
                      }
                    },
                    {
                      "type": "object",
                      "additionalProperties": false,
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "tenant_inactive"
                          ]
                        },
                        "code": {
                          "type": "string",
                          "enum": [
                            "tenant_inactive"
                          ]
                        },
                        "requestId": {
                          "type": "string"
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "scopeForbidden": {
                    "summary": "The presented key lacks the required scope",
                    "value": {
                      "error": "API key does not have write:identity scope",
                      "requestId": "req-test"
                    }
                  },
                  "tenantInactive": {
                    "summary": "action:'verify' — tenant went inactive before spend reservation",
                    "value": {
                      "error": "tenant_inactive",
                      "code": "tenant_inactive",
                      "requestId": "req-test"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/GatedNotFound"
          },
          "409": {
            "description": "A conflicting in-flight or idempotency-key-bound request (`action:'verify'` only).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConflictError"
                },
                "example": {
                  "error": "idempotency_conflict",
                  "code": "example-code",
                  "ok": true,
                  "verificationId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                  "reasonCodes": [
                    "request_in_progress"
                  ],
                  "requestId": "req-test"
                }
              }
            }
          },
          "413": {
            "$ref": "#/components/responses/BodyTooLarge"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`action:'mint'`: the nonce-issuing KV write failed (fail-safe: no partially-written or unusable nonce is ever returned to the caller). `action:'verify'`: `kyc_verify_unavailable` — a transient fault while resolving pricing or reserving spend. Retryable; `Retry-After` carries the suggested backoff in seconds. Distinct from `spend_cap_reached` (402, a real business-state refusal, never an infrastructure fault); the request is not terminally denied.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until a retry is likely to succeed (`action:'verify'` faults only)."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "examples": {
                  "mintKvFault": {
                    "summary": "action:'mint' — nonce KV write failed",
                    "value": {
                      "error": "invalid_request",
                      "requestId": "req-test"
                    }
                  },
                  "verifyUnavailable": {
                    "summary": "action:'verify' — transient reservation-authority fault",
                    "value": {
                      "error": "kyc_verify_unavailable",
                      "code": "kyc_verify_unavailable",
                      "requestId": "req-test"
                    }
                  }
                }
              }
            }
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/kyc/verify/{verificationId}/address-document": {
      "post": {
        "operationId": "kycAddressDocumentCrossMatch",
        "tags": [
          "KYC Cross-Validation"
        ],
        "summary": "Cross-match a self-uploaded proof-of-address document",
        "description": "Re-OCRs a proof-of-address document (already uploaded as KYC evidence) and the target verification's already-captured ID-front document, then runs a deterministic name/address/freshness cross-match. This is the **only** cross-validation capability Noxtica offers today — it is a self-uploaded-document cross-match, **never** an authoritative registry lookup (USPS/Loqate/Experian), as the response's own `disclosure` field states. There is no generic OCR↔MRZ↔barcode consistency check.",
        "security": [
          {
            "ApiKeyAuth": [
              "write:identity"
            ]
          }
        ],
        "parameters": [
          {
            "name": "verificationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "evidenceObjectId"
                ],
                "properties": {
                  "evidenceObjectId": {
                    "type": "string",
                    "description": "The `objectId` of an already-finalized (`usable`) evidence object of kind `proof_of_address`, minted via `POST /v1/kyc/evidence/handle` + `POST /v1/kyc/evidence/finalize` against this same `verificationId`."
                  }
                }
              },
              "example": {
                "evidenceObjectId": "obj-front"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "A resolved cross-match verdict.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "verdict",
                    "disclosure",
                    "requestId"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "verdict": {
                      "type": "string",
                      "enum": [
                        "pass",
                        "review",
                        "reject"
                      ]
                    },
                    "disclosure": {
                      "type": "string",
                      "description": "The fixed, always-identical non-authoritative-result disclosure string."
                    },
                    "requestId": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "verdict": "pass",
                  "disclosure": "example-disclosure",
                  "requestId": "req-test"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/ScopeForbidden"
          },
          "404": {
            "$ref": "#/components/responses/GatedNotFound"
          },
          "409": {
            "description": "The verification has no captured front-document evidence to cross-match against.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "413": {
            "$ref": "#/components/responses/BodyTooLarge"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "Evidence unavailable, or the owned OCR inference service could not be reached.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          }
        },
        "x-noxtica-status": "partial"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/kyc/verify/batch": {
      "post": {
        "operationId": "kycVerifyBatchSubmit",
        "tags": [
          "KYC Batch"
        ],
        "summary": "Submit a batch verification manifest",
        "description": "Submits a CSV (`text/csv`) or JSON (`application/json`, `{\"items\":[...]}`) manifest of up to 500 rows. Each well-formed row is admitted **asynchronously**, off the response path, through the identical `POST /v1/kyc/verify` admission entry point — this endpoint does not verify anything itself, it only records per-item outcomes.",
        "security": [
          {
            "ApiKeyAuth": [
              "write:identity"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKeyRequired"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/KycBatchManifestJson"
              },
              "example": {
                "items": [
                  {
                    "id_type": "passport",
                    "purpose": "identity_verification",
                    "payload": {}
                  }
                ]
              }
            },
            "text/csv": {
              "schema": {
                "type": "string",
                "description": "Header row must include `id_type` (required); `purpose` and payload columns are optional."
              },
              "example": "id_type,purpose\npassport,identity_verification\n"
            }
          }
        },
        "responses": {
          "200": {
            "description": "A replayed idempotency key — the original batch job, unchanged.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KycBatchSubmitResponse"
                },
                "example": {
                  "ok": true,
                  "batchId": "batch_5a1f9c3e7b2d4a6f8091c2d3e4f5a6b7",
                  "status": "processing",
                  "itemCount": 1,
                  "items": [
                    {
                      "rowIndex": 0,
                      "status": "pending",
                      "errorCode": "missing_id_type"
                    }
                  ],
                  "requestId": "req-test"
                }
              }
            }
          },
          "202": {
            "description": "Accepted; items begin admitting asynchronously.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KycBatchSubmitResponse"
                },
                "example": {
                  "ok": true,
                  "batchId": "batch_5a1f9c3e7b2d4a6f8091c2d3e4f5a6b7",
                  "status": "processing",
                  "itemCount": 1,
                  "items": [
                    {
                      "rowIndex": 0,
                      "status": "pending",
                      "errorCode": "missing_id_type"
                    }
                  ],
                  "requestId": "req-test"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/ScopeForbidden"
          },
          "404": {
            "$ref": "#/components/responses/GatedNotFound"
          },
          "413": {
            "$ref": "#/components/responses/BodyTooLarge"
          },
          "415": {
            "description": "Unrecognized content type.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "Batch admission is temporarily unavailable (digest secret unset).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/kyc/verify/batch/{batchId}/status": {
      "get": {
        "operationId": "kycVerifyBatchStatus",
        "tags": [
          "KYC Batch"
        ],
        "summary": "Read a batch job's aggregate status",
        "security": [
          {
            "ApiKeyAuth": [
              "write:identity"
            ]
          }
        ],
        "parameters": [
          {
            "name": "batchId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The job-level aggregate.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KycBatchStatusResponse"
                },
                "example": {
                  "ok": true,
                  "batchId": "batch_5a1f9c3e7b2d4a6f8091c2d3e4f5a6b7",
                  "status": "processing",
                  "itemCount": 1,
                  "pendingCount": 0,
                  "admittedCount": 1,
                  "completedCount": 0,
                  "rejectedCount": 0,
                  "cancelledCount": 0,
                  "requestId": "req-test"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/ScopeForbidden"
          },
          "404": {
            "$ref": "#/components/responses/GatedNotFound"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/kyc/verify/batch/{batchId}/results": {
      "get": {
        "operationId": "kycVerifyBatchResults",
        "tags": [
          "KYC Batch"
        ],
        "summary": "Read a batch job's per-item outcomes",
        "security": [
          {
            "ApiKeyAuth": [
              "write:identity"
            ]
          }
        ],
        "parameters": [
          {
            "name": "batchId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Every row's outcome, malformed or not — never silently dropped.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KycBatchResultsResponse"
                },
                "example": {
                  "ok": true,
                  "batchId": "batch_5a1f9c3e7b2d4a6f8091c2d3e4f5a6b7",
                  "items": [
                    {
                      "rowIndex": 0,
                      "status": "pending",
                      "verificationId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                      "verdict": "verified",
                      "errorCode": "missing_id_type"
                    }
                  ],
                  "requestId": "req-test"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/ScopeForbidden"
          },
          "404": {
            "$ref": "#/components/responses/GatedNotFound"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/kyc/verify/batch/{batchId}/cancel": {
      "post": {
        "operationId": "kycVerifyBatchCancel",
        "tags": [
          "KYC Batch"
        ],
        "summary": "Cancel every still-pending item of a batch",
        "description": "A compare-and-swap `UPDATE ... WHERE status = 'pending'`. An item already `admitted`/`evaluating`/`completed` already holds (or held) a real verification claim and is never retroactively un-admitted.",
        "security": [
          {
            "ApiKeyAuth": [
              "write:identity"
            ]
          }
        ],
        "parameters": [
          {
            "name": "batchId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Cancellation applied to every still-pending row.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "batchId": {
                      "type": "string"
                    },
                    "cancelledCount": {
                      "type": "integer"
                    },
                    "requestId": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "batchId": "batch_5a1f9c3e7b2d4a6f8091c2d3e4f5a6b7",
                  "cancelledCount": 0,
                  "requestId": "req-test"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/ScopeForbidden"
          },
          "404": {
            "$ref": "#/components/responses/GatedNotFound"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/kyc/reverify": {
      "post": {
        "operationId": "kycReverify",
        "tags": [
          "KYC Reverify"
        ],
        "summary": "Re-check an already-established identity's device/verification level",
        "description": "A metered, read-shaped check against the authoritative device registry — it does not re-run document/biometric capture. Requires the device-registry module to be enabled for your organisation in addition to the KYC module; when it is not, the route answers the `GatedNotFound` 404.",
        "security": [
          {
            "ApiKeyAuth": [
              "write:identity"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "subjectId"
                ],
                "properties": {
                  "subjectId": {
                    "type": "string"
                  },
                  "requiredLevel": {
                    "type": "string",
                    "enum": [
                      "verified",
                      "partial",
                      "unverified",
                      "inconclusive"
                    ]
                  },
                  "stepUpReference": {
                    "type": "string",
                    "maxLength": 128,
                    "pattern": "^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$",
                    "description": "Optional biometric step-up claim reference (single-use)."
                  }
                }
              },
              "example": {
                "subjectId": "subj_4821",
                "requiredLevel": "verified",
                "stepUpReference": "example-stepUpReference"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Always 200 (FR-6 fail-closed discipline) — a subject-not-found or infra fault is a `verified:false` body, never a 5xx.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "verified": {
                      "type": "boolean"
                    },
                    "verificationLevel": {
                      "type": "string",
                      "enum": [
                        "verified",
                        "partial",
                        "unverified",
                        "inconclusive"
                      ]
                    },
                    "stepUp": {
                      "type": "string",
                      "enum": [
                        "satisfied",
                        "unconfigured",
                        "reference_required",
                        "reference_replayed",
                        "no_match",
                        "error"
                      ]
                    },
                    "requestId": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "verified": true,
                  "verificationLevel": "verified",
                  "stepUp": "satisfied",
                  "requestId": "req-test"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/ScopeForbidden"
          },
          "404": {
            "$ref": "#/components/responses/GatedNotFound"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/kyc/evidence/handle": {
      "post": {
        "operationId": "kycEvidenceHandleMint",
        "tags": [
          "KYC Evidence"
        ],
        "summary": "Mint a single-use ciphertext-upload handle",
        "description": "Step 1 of 2 for raw evidence storage. Mints an opaque, short-lived (15-minute) upload handle plus a fresh per-object Data Encryption Key (DEK) wrapped under the tenant's active Key Encryption Key (KEK). The caller encrypts the evidence bytes client-side with the returned `dek` and presents only ciphertext to `POST /v1/kyc/evidence/finalize` — Noxtica's server never sees plaintext evidence at this step. No R2 storage URL, internal key, or `sk_` value is ever returned (D27).",
        "security": [
          {
            "ApiKeyAuth": [
              "write:identity"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "verificationId",
                  "jurisdiction",
                  "evidenceKind",
                  "purpose",
                  "contentType",
                  "contentLength"
                ],
                "properties": {
                  "verificationId": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "jurisdiction": {
                    "type": "string",
                    "enum": [
                      "TR",
                      "EU",
                      "US"
                    ],
                    "description": "Must equal the tenant's configured evidence residency; any mismatch is a 404 (no residency-probe oracle)."
                  },
                  "evidenceKind": {
                    "type": "string",
                    "enum": [
                      "id_document_front",
                      "id_document_back",
                      "document_front",
                      "document_back",
                      "passport_page",
                      "proof_of_address",
                      "selfie_image",
                      "document_near_face",
                      "liveness_video",
                      "liveness_recording",
                      "liveness_sequence",
                      "voice_sample",
                      "speech_audio",
                      "supporting_document",
                      "document_data"
                    ],
                    "description": "Closed evidence-kind catalog (this enum is the complete set). e.g. id_document_front, proof_of_address, selfie_image. NOTE: id_front/id_back/selfie are NOT members of this catalog (a prior stale example here caused exactly that drift in downstream SDKs)."
                  },
                  "purpose": {
                    "type": "string",
                    "description": "Closed evidence-purpose catalog (e.g. identity_verification, address_verification)."
                  },
                  "contentType": {
                    "type": "string",
                    "example": "image/jpeg"
                  },
                  "contentLength": {
                    "type": "integer",
                    "minimum": 1
                  }
                }
              },
              "example": {
                "verificationId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                "jurisdiction": "TR",
                "evidenceKind": "id_document_front",
                "purpose": "identity_verification",
                "contentType": "image/jpeg",
                "contentLength": 1
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Handle minted.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "handle": {
                      "type": "string",
                      "description": "Opaque signed single-use upload handle."
                    },
                    "dek": {
                      "type": "string",
                      "description": "Base64 plaintext DEK — hold only in memory, never log or persist raw."
                    },
                    "wrappedDek": {
                      "type": "string",
                      "description": "The same DEK wrapped under the active KEK, for reference/audit only."
                    },
                    "envelope": {
                      "type": "object",
                      "properties": {
                        "envelope_version": {
                          "type": "integer"
                        },
                        "cipher_suite": {
                          "type": "string"
                        },
                        "kek_kid": {
                          "type": "string"
                        }
                      }
                    },
                    "uploadTarget": {
                      "type": "object",
                      "properties": {
                        "objectId": {
                          "type": "string"
                        },
                        "schemaVersion": {
                          "type": "integer"
                        }
                      }
                    },
                    "expiresAt": {
                      "type": "integer",
                      "description": "Unix ms handle expiry."
                    },
                    "requestId": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "handle": "example-handle",
                  "dek": "example-dek",
                  "wrappedDek": "example-wrappedDek",
                  "envelope": {
                    "envelope_version": 1,
                    "cipher_suite": "example-cipher_suite",
                    "kek_kid": "example-kek_kid"
                  },
                  "uploadTarget": {
                    "objectId": "example-objectId",
                    "schemaVersion": 1
                  },
                  "expiresAt": 1768435200,
                  "requestId": "req-test"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/ScopeForbidden"
          },
          "404": {
            "$ref": "#/components/responses/GatedNotFound"
          },
          "413": {
            "$ref": "#/components/responses/BodyTooLarge"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "Evidence storage temporarily unavailable (handle secret or KEK unresolved).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/kyc/evidence/finalize": {
      "post": {
        "operationId": "kycEvidenceFinalize",
        "tags": [
          "KYC Evidence"
        ],
        "summary": "Upload sealed ciphertext and finalize the evidence object",
        "description": "Step 2 of 2. Presents the handle from `POST /v1/kyc/evidence/handle` plus the chunked-AEAD-sealed ciphertext body. The server performs a controlled in-memory decrypt → structural inspection (never persisting plaintext) and promotes the object to `usable` or `rejected`. A repeated call with the same handle/body replays the stored terminal result byte-for-byte (idempotent by construction, not by an `Idempotency-Key` header).",
        "security": [
          {
            "ApiKeyAuth": [
              "write:identity"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "handle",
                  "objectId",
                  "commitment",
                  "chunks"
                ],
                "properties": {
                  "handle": {
                    "type": "string",
                    "description": "The opaque handle from the mint step."
                  },
                  "objectId": {
                    "type": "string"
                  },
                  "commitment": {
                    "type": "object",
                    "required": [
                      "total_chunks",
                      "total_plaintext_length"
                    ],
                    "properties": {
                      "total_chunks": {
                        "type": "integer",
                        "minimum": 1
                      },
                      "total_plaintext_length": {
                        "type": "integer",
                        "minimum": 0
                      }
                    }
                  },
                  "chunks": {
                    "type": "array",
                    "description": "Chunked-AEAD-sealed ciphertext chunks (schema version carried in the mint-step envelope).",
                    "items": {
                      "type": "string"
                    }
                  }
                }
              },
              "example": {
                "handle": "example-handle",
                "objectId": "example-objectId",
                "commitment": {
                  "total_chunks": 1,
                  "total_plaintext_length": 0
                },
                "chunks": [
                  "example-chunks"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Terminal inspection outcome.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "state",
                    "objectId",
                    "requestId"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "state": {
                      "type": "string",
                      "enum": [
                        "usable",
                        "rejected"
                      ]
                    },
                    "reasonCode": {
                      "type": "string",
                      "enum": [
                        "evidence_kind_forbidden",
                        "evidence_mime_mismatch",
                        "evidence_size_mismatch",
                        "evidence_pixels_invalid",
                        "evidence_unreadable"
                      ],
                      "description": "Present only when `state` is `rejected`."
                    },
                    "objectId": {
                      "type": "string"
                    },
                    "requestId": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "state": "usable",
                  "reasonCode": "evidence_kind_forbidden",
                  "objectId": "example-objectId",
                  "requestId": "req-test"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/InvalidApiKey"
          },
          "403": {
            "description": "The presented handle failed verification (signature, expiry, manifest, or binding mismatch) — a single uniform refusal, no probe oracle.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/GatedNotFound"
          },
          "413": {
            "$ref": "#/components/responses/BodyTooLarge"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "Evidence storage temporarily unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/kyc/sessions": {
      "post": {
        "operationId": "kycSessionMint",
        "tags": [
          "KYC Hosted Sessions"
        ],
        "summary": "Mint a Noxtica-hosted KYC verification-session link",
        "description": "Server-to-server. Creates a hosted verification session and returns a one-shot,\nopaque URL to hand to your end customer (redirect, email, SMS or QR). The URL embeds a\nbearer session token that is never returned again by any route: treat it as a secret,\ndo not log it and do not put it in an analytics URL. Minting is free; the verification is\ncounted when the customer submits.\n\n**Before you can mint.** (1) The identity verification module must be enabled for your organisation;\nuntil it is, this route answers the same byte-identical `404` as an unknown path. (2) Your\n`sk_` key needs the `write:identity` scope (a key created with the default scope is\nrefused with `403`). (3) A tenant administrator must have recorded an active legal-basis\nreceipt for hosted document capture in the Backoffice; without it the mint is refused with\n`403 kyc_legal_basis_receipt_required`. Noxtica never selects a legal basis for you. (4)\nYour organisation needs a hosted configuration (business name, privacy URL, supported\ndocuments) in the Backoffice, or the customer sees \"Verification isn't ready yet\"; the mint\nitself does not check this.\n\n**Request.** `subjectRef` is required. The expiry field is `expiresInSeconds`: a key named\n`ttlSeconds` is not read and is silently ignored (the link then lasts the 24 hour default).\nUnknown keys are ignored. The snake_case spellings `subject_ref`, `return_url`,\n`id_type`, `expires_in_seconds` and `hosted_options` are also accepted; the camelCase names\nare the contract. Locale, customer name, email and phone are not request fields: the page\nlanguage follows the customer's browser and cannot be forced, and the webhook endpoint is\nregistered once for your organisation in the Backoffice, not per session.\n\n**Lifetime.** An unopened link keeps `expiresInSeconds` (default 24 hours). Once the\ncustomer first opens it the deadline tightens to `min(expiresAt, openedAt + 30 minutes)`;\nthe customer must finish capture inside that window. `expiresAt` in every response is\nUnix time in **milliseconds**.\n\n**Using the link.** The hosted page cannot be embedded in an iframe (`X-Frame-Options:\nDENY`); open it in a new tab, or redirect the customer to it. The page never posts a\nmessage to the opener or parent window and never redirects on its own. If you minted with\na `returnUrl`, the page shows a plain \"Return to <business>\" link to exactly that URL\n(nothing is appended) on the completion and status screens only for a completed outcome,\nand on the screen shown when a step cannot continue. Sessions created from Backoffice\ninvitations carry no `returnUrl`. Correlate by the `sessionId` you stored at mint, and\nnever treat a visit to your return page as proof of completion.\n\n**Outcome.** Learn the outcome with the `kyc.session.completed` webhook or by polling\n`GET /v1/kyc/sessions/{sessionId}`. With the identity provider configured today every\nsuccessful capture ends in `review_pending`, not `completed`: the webhook fires only\nafter a Backoffice reviewer approves the case (allow up to about 5 minutes after the\ndecision), and a `review_pending` session never expires. See that route for the\nstatus table.\n\n**Email verification (optional step).** `hostedOptions.steps.emailVerification`\n(`off`, `optional` or `required`) adds an email-verification step to the hosted flow: the\ncustomer types an address, receives one confirmation link, and only a click on that link\nmarks the address verified. Omit the key to use your organisation's default (Hosted\nconfiguration); an explicit value for this link wins in both directions. The effective\nmode is resolved once, here, and is fixed for the session. This is available only once the\nplatform has enabled hosted email verification: until then an explicit `optional` or\n`required` is refused with `400 email_verification_unavailable` (an explicit `off` is\nalways accepted, and your organisation default is ignored), so a `required` session can\nnever silently run unverified.\n\n**Idempotency.** `Idempotency-Key` is optional (8 to 128 characters). Without it every\ncall mints a fresh session. With it, a retry under the same key returns the SAME session\nwith `replayed: true` and WITHOUT the `url`: the one-shot URL of a lost response cannot be\nrecovered, so mint a new session under a new key instead. The replay matches on the key\nonly; a different body under the same key still returns the original session.\n\n**Rate limits.** A per-source-IP limit applies first, before authentication, then a per-key limit\nshared with the status read. See \"Rate limits\" above.",
        "security": [
          {
            "ApiKeyAuth": [
              "write:identity"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKeyOptional"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "subjectRef"
                ],
                "properties": {
                  "subjectRef": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 256,
                    "description": "Your own opaque reference for this end customer (trimmed, non-empty). It is returned to you as `subjectId` on the status read and is the identifier an erasure request targets. It is never sent in webhooks."
                  },
                  "returnUrl": {
                    "type": "string",
                    "format": "uri",
                    "maxLength": 2048,
                    "pattern": "^https://",
                    "description": "Where the \"Return to <business>\" link on the hosted page points. `https` only, no user info, at most 2048 characters, and the host must exactly equal (case insensitive) an entry in your organisation's approved return hosts (`allowedReturnUrlHosts` in the Backoffice hosted configuration; at most 20 entries, host names only, no wildcards; port, path and query are not checked). An organisation with no approved hosts cannot send a `returnUrl`. Anything else is refused with `400 return_url_not_allowed`. The page appends nothing to it."
                  },
                  "purpose": {
                    "type": "string",
                    "maxLength": 500,
                    "description": "Shown to the customer on the consent screen. Falls back to your organisation's default purpose. More than 500 characters is refused with `400 invalid_request`."
                  },
                  "idType": {
                    "type": "string",
                    "enum": [
                      "national_id",
                      "passport",
                      "driving_license",
                      "residence_permit"
                    ],
                    "description": "Document type hint; it must be one of `hostedOptions.allowedDocumentTypes` (default: the first allowed type, `national_id` when `hostedOptions` is omitted), else `400 invalid_id_type`. The customer still chooses the type and issuing country on the page from the allowed types your organisation configured."
                  },
                  "expiresInSeconds": {
                    "type": "integer",
                    "minimum": 300,
                    "maximum": 604800,
                    "default": 86400,
                    "description": "Lifetime of the UNOPENED link in seconds: 5 minutes to 7 days, default 24 hours. A value outside the range or a non-integer is refused with `400 invalid_request` (it is not clamped). After the customer opens the link the 30 minute capture window applies."
                  },
                  "hostedOptions": {
                    "$ref": "#/components/schemas/KycHostedSessionOptions"
                  }
                }
              },
              "example": {
                "subjectRef": "cust_4821",
                "returnUrl": "https://merchant.example.com/kyc/return",
                "purpose": "Open your brokerage account",
                "idType": "passport",
                "expiresInSeconds": 3600,
                "hostedOptions": {
                  "allowedDocumentTypes": [
                    "passport",
                    "national_id"
                  ],
                  "allowDeviceUpload": false,
                  "steps": {
                    "documentBack": "auto",
                    "documentNearFace": false,
                    "activeLiveness": true,
                    "speechAnalysis": false,
                    "ageGenderEstimation": false
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Session minted, or (idempotent replay) the existing session returned without its URL.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "sessionId",
                    "expiresAt",
                    "requestId"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "sessionId": {
                      "type": "string",
                      "format": "uuid",
                      "description": "The session id. Store it with your customer record; it is the correlation handle for status reads and webhooks."
                    },
                    "url": {
                      "type": "string",
                      "format": "uri",
                      "description": "One-shot hosted-flow URL; the ONLY place the bearer token is ever returned. Absent on an idempotent replay."
                    },
                    "expiresAt": {
                      "type": "integer",
                      "format": "int64",
                      "description": "Unix time in milliseconds at which the unopened link expires."
                    },
                    "replayed": {
                      "type": "boolean",
                      "enum": [
                        true
                      ],
                      "description": "Present (and `true`) only when an `Idempotency-Key` matched an existing session; `url` is then absent."
                    },
                    "hostedOptions": {
                      "allOf": [
                        {
                          "$ref": "#/components/schemas/KycHostedSessionOptions"
                        }
                      ],
                      "description": "The effective hosted options stored with the session, including the resolved `steps.emailVerification` mode (your organisation default applied when the request did not set it). Present only when hosted email verification is enabled for the platform AND the session's effective mode is not `off`; absent otherwise (a session that does not use the step gets the pre-feature response)."
                    },
                    "requestId": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "created": {
                    "summary": "Fresh mint",
                    "value": {
                      "ok": true,
                      "sessionId": "6d3c3a8e-6b4b-4a8f-8f4e-0a0e6b3d9d21",
                      "url": "https://verify.noxtica.com/s/kycs.tenant_42.q3JkT0vN8mYb1xW6cE4aZ7uP2sH9dLfR5gKiA0oXyUw",
                      "expiresAt": 1790765600000,
                      "requestId": "req-test"
                    }
                  },
                  "replayed": {
                    "summary": "Idempotent replay (no url)",
                    "value": {
                      "ok": true,
                      "sessionId": "6d3c3a8e-6b4b-4a8f-8f4e-0a0e6b3d9d21",
                      "expiresAt": 1790765600000,
                      "replayed": true,
                      "requestId": "req-test"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request` (unreadable JSON, `Idempotency-Key` outside 8 to 128 characters, `subjectRef` missing or longer than 256, `expiresInSeconds` outside 300 to 604800 or not an integer, `purpose` longer than 500, a bad `payload`), `invalid_id_type`, `invalid_hosted_options` (`hostedOptions` is not a complete, well-formed object, or `steps.emailVerification` is not one of `off`, `optional`, `required`), `return_url_not_allowed`, or `email_verification_unavailable` (an explicit `steps.emailVerification` of `optional` or `required` was requested but hosted email verification is not enabled for the platform).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KycSessionError"
                },
                "examples": {
                  "invalidRequest": {
                    "value": {
                      "error": "invalid_request",
                      "requestId": "req-test"
                    }
                  },
                  "returnUrlNotAllowed": {
                    "value": {
                      "error": "return_url_not_allowed",
                      "requestId": "req-test"
                    }
                  },
                  "emailVerificationUnavailable": {
                    "value": {
                      "error": "email_verification_unavailable",
                      "requestId": "req-test"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/InvalidApiKey"
          },
          "403": {
            "description": "The key lacks the `write:identity` scope; or `kyc_legal_basis_receipt_required` (no active hosted-capture legal-basis receipt for your organisation); or `age_gender_estimation_not_enabled` (`hostedOptions.steps.ageGenderEstimation` was `true` but the platform feature or your organisation's acknowledgement is missing; see `reasonCode`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KycSessionError"
                },
                "examples": {
                  "scope": {
                    "value": {
                      "error": "API key does not have write:identity scope",
                      "requestId": "req-test"
                    }
                  },
                  "legalBasisReceiptRequired": {
                    "value": {
                      "error": "kyc_legal_basis_receipt_required",
                      "requestId": "req-test"
                    }
                  },
                  "ageGenderNotEnabled": {
                    "value": {
                      "error": "age_gender_estimation_not_enabled",
                      "reasonCode": "age_gender_platform_disabled",
                      "requestId": "req-test"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/GatedNotFound"
          },
          "413": {
            "description": "`body_too_large` — the request body exceeds 32768 bytes.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KycSessionError"
                },
                "example": {
                  "error": "body_too_large",
                  "requestId": "req-test"
                }
              }
            }
          },
          "415": {
            "description": "The request is not `Content-Type: application/json` (body `invalid_request`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KycSessionError"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerMisconfigured"
          },
          "503": {
            "description": "Retryable unless noted. `tenant_module_gate_unavailable` (the module gate could not be answered; `Retry-After: 2`), `kyc_legal_basis_receipt_unavailable` (the receipt check faulted; `reason`, `Retry-After: 2`), `hosted_verify_not_configured` (the hosted deployment is not configured; contact support, no `Retry-After`), or `invalid_request` with a `reason` (a database or backend fault; `Retry-After: 2`). Retry a `503` with the SAME `Idempotency-Key`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KycSessionError"
                },
                "examples": {
                  "receiptCheckUnavailable": {
                    "value": {
                      "error": "kyc_legal_basis_receipt_unavailable",
                      "message": "The legal-basis receipt required for this request could not be confirmed",
                      "reason": "backend_unavailable",
                      "requestId": "req-test"
                    }
                  },
                  "moduleGateUnavailable": {
                    "value": {
                      "error": "tenant_module_gate_unavailable",
                      "message": "The tenant module gate could not be confirmed; retry shortly",
                      "requestId": "req-test"
                    }
                  },
                  "hostedVerifyNotConfigured": {
                    "value": {
                      "error": "hosted_verify_not_configured",
                      "requestId": "req-test"
                    }
                  },
                  "backendFault": {
                    "value": {
                      "error": "invalid_request",
                      "reason": "pg_unavailable",
                      "requestId": "req-test"
                    }
                  }
                }
              }
            }
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/kyc/sessions/{sessionId}": {
      "get": {
        "operationId": "kycSessionStatus",
        "tags": [
          "KYC Hosted Sessions"
        ],
        "summary": "Read a hosted session's current status (tenant backend read)",
        "description": "Server-to-server. The authoritative tenant-side read of a hosted session; use it to\nconfirm any webhook before you act on it, and to poll when you have no webhook endpoint.\nEverything is nested under `session`, and every timestamp is Unix time in\n**milliseconds**. A session that is past its deadline reads `200` with\n`status: \"expired\"` (never `410`; the `410` answers belong to the customer's browser\nroutes). A session id that does not exist, or belongs to another organisation, gets the\nsame byte-identical `404` as an unknown path.\n\n**Status lifecycle.**\n\n| `status` | Meaning | `kyc.session.*` webhook |\n|---|---|---|\n| `pending` | Minted; the customer has not opened the link. | none |\n| `opened` | The customer reached the capture page. | none |\n| `verifying` | The customer submitted; the verification is running. | none |\n| `review_pending` | The verification finished and awaits a Backoffice review decision. With the identity provider configured today every successful hosted capture lands here. It never expires. | **none yet**; it fires later as `completed` |\n| `completed` | A business decision exists: a reviewer approved or overrode the case (or, by design, a machine `verified`). | `kyc.session.completed` with `status: completed` |\n| `unverified` | Finished with a negative outcome and no manual-review code (for example capture attempts exhausted). | `kyc.session.completed` with `status: unverified` |\n| `error` | A provider or infrastructure fault, or the submit was refused at admission. | `kyc.session.completed` with `status: error` |\n| `expired` | Past the deadline without a decision. | never |\n| `cancelled_by_user` | The customer cancelled on the hosted page (only when cancellation is enabled for your organisation). | `kyc.session.cancelled` |\n\n**`review_pending` to `completed`.** `kyc.session.completed` does not fire when a session\nlands in `review_pending`. It fires when a Backoffice reviewer approves or overrides the\ncase; allow up to about 5 minutes between the decision and the delivery. Until then the\nonly way to observe `review_pending` is this read. A rejected end state is not currently\nexpressible by the review vocabulary.\n\n**Cancellation.** `status: cancelled_by_user` is reported here, but `cancelledAt` and\n`cancelReason` are NOT part of this response; they are delivered in the\n`kyc.session.cancelled` webhook. An expiry emits no webhook at all. A cancelled or expired\nsession is never billed as a verification (the `kyc.verification` meter is recorded only\nat submit-time admission); only the request-level `endpoint.collect.request` counts.\n\n**Email verification result.** Only when hosted email verification is enabled for the\nplatform AND the session's effective mode is not `off` or an address is stored, the\n`session` object also carries `email` (the normalised address the customer entered, or\n`null`), `emailVerified` (`true` only after the customer clicked the confirmation link for\nthat exact address), `emailVerifiedAt` (Unix ms, or `null`) and `emailVerification` (the\neffective mode: `off`, `optional` or `required`). Treat `email` with `emailVerified: false`\nas an unverified, customer-typed value. Otherwise these four keys are absent.\n\n**Noxtica Verification ID.** Only when the Noxtica Verification ID (NVID) is enabled for\nthe platform, the `session` object also carries `nvid`: the session's NVID\n(`NVID-XXXX-XXXX-XXXX-XXXX`) or `null` (none was issued: an NVID is issued when the\nsubmit ends `completed` or `review_pending`). The key is absent while the feature is not\nenabled. The public status page of an NVID is `https://verify.<environment host>/v/<NVID>`;\nthe public lookup route behind it can only be called from the hosted site's browser\norigin, never from a tenant backend.\n\n**Rate limit.** Shares the per-key limit (30 requests per 60 seconds) with the mint call,\nafter the per-source-IP limit that applies to every request.",
        "security": [
          {
            "ApiKeyAuth": [
              "write:identity"
            ]
          }
        ],
        "parameters": [
          {
            "name": "sessionId",
            "in": "path",
            "required": true,
            "description": "The `sessionId` returned by the mint call.",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9-]{1,64}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The session's current status.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KycTenantSessionEnvelope"
                },
                "example": {
                  "ok": true,
                  "session": {
                    "id": "6d3c3a8e-6b4b-4a8f-8f4e-0a0e6b3d9d21",
                    "status": "review_pending",
                    "idType": "passport",
                    "subjectId": "cust_4821",
                    "captureStep": "submit",
                    "createdAt": 1790762000000,
                    "openedAt": 1790762100000,
                    "expiresAt": 1790763900000,
                    "completedAt": 1790762445000,
                    "verificationId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                    "reasonCodes": [
                      "provider_manual_review"
                    ],
                    "purpose": "Open your brokerage account",
                    "returnUrl": "https://merchant.example.com/kyc/return",
                    "selectedIdType": "passport",
                    "selectedIssuingCountry": "GB",
                    "consentVersion": "2026-09-01",
                    "consentAcceptedAt": 1790762110000,
                    "speechProfilingConsentAcceptedAt": null,
                    "ageGenderConsentAcceptedAt": null,
                    "evidence": {
                      "front": "obj_9c1e4a",
                      "selfie": "obj_5b7d02"
                    },
                    "decision": {
                      "outcome": "review_pending",
                      "reasonCodes": [
                        "provider_manual_review"
                      ],
                      "decidedAt": 1790762445000
                    },
                    "stages": {
                      "scene_inventory": {
                        "status": "pass",
                        "score": 0.97,
                        "reasonCodes": []
                      },
                      "document_type_id": {
                        "status": "pass",
                        "score": 0.94,
                        "reasonCodes": []
                      },
                      "ocr_back": {
                        "status": "skipped",
                        "score": null,
                        "reasonCodes": [
                          "not_required"
                        ]
                      },
                      "mrz_crosscheck": {
                        "status": "pass",
                        "score": 0.99,
                        "reasonCodes": []
                      },
                      "selfie_quality": {
                        "status": "pass",
                        "score": 0.91,
                        "reasonCodes": []
                      },
                      "document_near_face": {
                        "status": "skipped",
                        "score": null,
                        "reasonCodes": [
                          "not_required"
                        ]
                      },
                      "active_liveness": {
                        "status": "pass",
                        "score": 0.93,
                        "reasonCodes": []
                      },
                      "speech_profile": {
                        "status": "skipped",
                        "score": null,
                        "reasonCodes": [
                          "speech_profiling_not_requested"
                        ]
                      },
                      "speech_analysis": {
                        "status": "skipped",
                        "score": null,
                        "reasonCodes": [
                          "speech_analysis_not_requested"
                        ]
                      },
                      "age_gender": {
                        "status": "skipped",
                        "score": null,
                        "reasonCodes": [
                          "age_gender_not_requested"
                        ]
                      }
                    },
                    "scorecard": {
                      "document_front": {
                        "status": "pass",
                        "score": 0.94,
                        "checks": [],
                        "reasonCodes": []
                      },
                      "document_back": {
                        "status": "skipped",
                        "score": 0,
                        "checks": [],
                        "reasonCodes": [
                          "not_required"
                        ]
                      },
                      "selfie": {
                        "status": "pass",
                        "score": 0.91,
                        "checks": [],
                        "reasonCodes": []
                      },
                      "liveness": {
                        "status": "pass",
                        "score": 0.93,
                        "checks": [],
                        "reasonCodes": []
                      },
                      "voice": {
                        "status": "skipped",
                        "score": 0,
                        "checks": [],
                        "reasonCodes": [
                          "not_required"
                        ]
                      },
                      "cross_validation": {
                        "status": "pass",
                        "score": 0.99,
                        "checks": [],
                        "reasonCodes": []
                      },
                      "overall": {
                        "status": "pass",
                        "score": 0.94,
                        "checks": [],
                        "reasonCodes": []
                      }
                    },
                    "nvid": "NVID-7K3M-Q9XA-T2RW-4HZD"
                  },
                  "requestId": "req-test"
                }
              }
            }
          },
          "400": {
            "description": "`Invalid sessionId` — the path segment is not valid percent-encoding.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KycSessionError"
                },
                "example": {
                  "error": "Invalid sessionId",
                  "requestId": "req-test"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/ScopeForbidden"
          },
          "404": {
            "$ref": "#/components/responses/GatedNotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerMisconfigured"
          },
          "503": {
            "description": "Retryable (`Retry-After: 2`). `tenant_module_gate_unavailable`, or `invalid_request` with a `reason` (`pg_unavailable` or `backend_unavailable`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KycSessionError"
                },
                "examples": {
                  "moduleGateUnavailable": {
                    "value": {
                      "error": "tenant_module_gate_unavailable",
                      "message": "The tenant module gate could not be confirmed; retry shortly",
                      "requestId": "req-test"
                    }
                  },
                  "backendFault": {
                    "value": {
                      "error": "invalid_request",
                      "reason": "pg_unavailable",
                      "requestId": "req-test"
                    }
                  }
                }
              }
            }
          }
        },
        "x-noxtica-status": "available",
        "x-noxtica-webhook-data": {
          "kyc.session.completed": {
            "$ref": "#/components/schemas/KycSessionCompletedWebhookData"
          },
          "kyc.session.cancelled": {
            "$ref": "#/components/schemas/KycSessionCancelledWebhookData"
          }
        }
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/kyc/session-view": {
      "get": {
        "operationId": "kycSessionView",
        "tags": [
          "KYC Hosted Sessions"
        ],
        "summary": "Read the current hosted session (browser-facing)",
        "description": "Called by the hosted verification page itself, never by a tenant backend.\n**Noxtica Verification ID.** Only when the Noxtica Verification ID (NVID) is enabled for the platform, the `session` object carries `verificationIdentifier` (`KycVerificationIdentifier`) — the NVID with its derived status and an `emailOnFile` flag — or `null` when the session has no NVID. It lets the page show the ID again when a finished link is reloaded. The key is absent while the feature is not enabled; the email address is never returned.",
        "security": [
          {
            "SessionTokenAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "The session snapshot.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KycHostedSessionEnvelope"
                },
                "example": {
                  "ok": true,
                  "session": {
                    "status": "opened",
                    "idType": "passport",
                    "captureStep": "consent",
                    "expiresAt": 1790763900000,
                    "openedAt": 1790762100000,
                    "steps": [
                      "consent",
                      "id_front",
                      "id_back",
                      "selfie",
                      "document_near_face",
                      "liveness",
                      "voice",
                      "review",
                      "submit"
                    ],
                    "configuration": {
                      "businessName": "Example Bank",
                      "purpose": "Open your brokerage account",
                      "privacyUrl": "https://merchant.example.com/privacy",
                      "supportUrl": "https://merchant.example.com/support",
                      "returnUrl": "https://merchant.example.com/kyc/return",
                      "privacyVersion": "2026-09-01",
                      "documents": [
                        {
                          "idType": "passport",
                          "issuingCountries": [
                            "GB"
                          ],
                          "requireBack": false
                        }
                      ],
                      "requireSelfie": true,
                      "requireVoice": false,
                      "livenessMode": "passive",
                      "options": {
                        "allowedDocumentTypes": [
                          "passport"
                        ],
                        "allowDeviceUpload": false,
                        "steps": {
                          "documentBack": "auto",
                          "documentNearFace": false,
                          "activeLiveness": true,
                          "speechAnalysis": false
                        }
                      }
                    },
                    "selection": null,
                    "consent": null,
                    "evidence": {},
                    "resume": {
                      "eligible": true
                    },
                    "failureBudget": {
                      "front": {
                        "attempts": 0,
                        "max": 10
                      },
                      "back": {
                        "attempts": 0,
                        "max": 10
                      },
                      "selfie": {
                        "attempts": 0,
                        "max": 10
                      },
                      "liveness": {
                        "attempts": 0,
                        "max": 3
                      },
                      "voice": {
                        "attempts": 0,
                        "max": 10
                      },
                      "upload": {
                        "attempts": 0,
                        "max": 3
                      }
                    },
                    "serverNow": 1790762150000,
                    "sessionExpiresAt": 1790763900000
                  },
                  "requestId": "req-test"
                }
              }
            }
          },
          "403": {
            "description": "Missing/disallowed Origin, or an invalid/expired session token.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/GatedNotFound"
          },
          "410": {
            "$ref": "#/components/responses/SessionExpiredOrCancelled"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/kyc/session-progress": {
      "post": {
        "operationId": "kycSessionProgress",
        "tags": [
          "KYC Hosted Sessions"
        ],
        "summary": "Checkpoint hosted-flow progress (browser-facing)",
        "description": "Records consent, document/issuing-country selection, and step completion as the customer moves through the hosted flow.",
        "security": [
          {
            "SessionTokenAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "Progress-checkpoint payload (consent, selection, or step-completion — shape depends on the current step)."
              },
              "example": {}
            }
          }
        },
        "responses": {
          "200": {
            "description": "Checkpoint recorded; returns the updated snapshot.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KycHostedSessionEnvelope"
                },
                "example": {
                  "ok": true,
                  "session": {
                    "status": "opened",
                    "idType": "passport",
                    "captureStep": "id_front",
                    "expiresAt": 1790763900000,
                    "openedAt": 1790762100000,
                    "steps": [
                      "consent",
                      "id_front",
                      "id_back",
                      "selfie",
                      "document_near_face",
                      "liveness",
                      "voice",
                      "review",
                      "submit"
                    ],
                    "configuration": {
                      "businessName": "Example Bank",
                      "purpose": "Open your brokerage account",
                      "privacyUrl": "https://merchant.example.com/privacy",
                      "supportUrl": "https://merchant.example.com/support",
                      "returnUrl": "https://merchant.example.com/kyc/return",
                      "privacyVersion": "2026-09-01",
                      "documents": [
                        {
                          "idType": "passport",
                          "issuingCountries": [
                            "GB"
                          ],
                          "requireBack": false
                        }
                      ],
                      "requireSelfie": true,
                      "requireVoice": false,
                      "livenessMode": "passive",
                      "options": {
                        "allowedDocumentTypes": [
                          "passport"
                        ],
                        "allowDeviceUpload": false,
                        "steps": {
                          "documentBack": "auto",
                          "documentNearFace": false,
                          "activeLiveness": true,
                          "speechAnalysis": false
                        }
                      }
                    },
                    "selection": {
                      "idType": "passport",
                      "issuingCountry": "GB"
                    },
                    "consent": {
                      "version": "2026-09-01",
                      "acceptedAt": 1790762110000
                    },
                    "evidence": {},
                    "resume": {
                      "eligible": true
                    },
                    "failureBudget": {
                      "front": {
                        "attempts": 0,
                        "max": 10
                      },
                      "back": {
                        "attempts": 0,
                        "max": 10
                      },
                      "selfie": {
                        "attempts": 0,
                        "max": 10
                      },
                      "liveness": {
                        "attempts": 0,
                        "max": 3
                      },
                      "voice": {
                        "attempts": 0,
                        "max": 10
                      },
                      "upload": {
                        "attempts": 0,
                        "max": 3
                      }
                    },
                    "serverNow": 1790762160000,
                    "sessionExpiresAt": 1790763900000
                  },
                  "requestId": "req-test"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "403": {
            "description": "Missing/disallowed Origin, or an invalid/expired session token.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/GatedNotFound"
          },
          "409": {
            "description": "The session is already terminal.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "410": {
            "$ref": "#/components/responses/SessionExpiredOrCancelled"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/kyc/session-cancel": {
      "post": {
        "operationId": "kycSessionCancel",
        "tags": [
          "KYC Hosted Sessions"
        ],
        "summary": "Cancel the hosted session (browser-facing)",
        "description": "Called by the hosted verification page when the end customer confirms they do not want to continue. Moves the session to the terminal status `cancelled_by_user`, recorded server-side (`cancelledAt`, optional closed-enum `cancelReason`); the cancel itself hard-deletes no evidence (evidence retention rules are unchanged).\n**Capability.** A collector that serves and has armed this route advertises it on every session snapshot (`GET /v1/kyc/session-view`, `POST /v1/kyc/session-progress`) as `session.capabilities.cancel: true`. When the field is absent (an older collector, or cancel disarmed) the hosted page never calls this route and shows a client-only end screen instead. An older or unarmed collector answers this route with the same byte-identical V1 `404` as any other gated route.\n**When it is allowed.** Cancel is accepted from any capture, consent, selection, or review step (session `pending` or `opened`). It is refused with `409 session_not_cancellable` once the session is `verifying` (the single-use submit gate is consumed and the verification is being paid for) or already `completed`, `unverified`, `error`, or `review_pending`. A session past its deadline answers `410 session_expired`.\n**Idempotency.** Repeating the call on an already-cancelled session returns `200` with the ORIGINAL `cancelledAt` and `cancelReason`.\n**After a cancel** every other customer route (`session-view`, `session-progress`, `session-submit`, `session-evidence/handle`, `session-evidence/finalize`) answers `410 session_cancelled` (`code: kyc_session_cancelled`).\n**Webhook.** The call that actually transitions the session emits ONE `kyc.session.cancelled` webhook to every enabled endpoint subscribed to that event type (subscription is opt-in per endpoint; nothing is sent to an endpoint that did not list it). The envelope `data` is `{schemaVersion: \"1\", sessionId, status: \"cancelled_by_user\", cancelReason (closed enum or `null`), cancelledAt (Unix ms), occurredAt (= cancelledAt), deliveryId}` — plus `email` and `emailVerified` when hosted email verification is enabled for the platform AND the session has a stored address (`KycSessionCancelledWebhookData`) — and carries no other subject data. An idempotent replay, a `409` and an expiry emit nothing. Delivery is at-least-once through the same signed outbox as `kyc.session.completed`; receivers MUST dedup by `deliveryId`. A webhook is a notification, not authority: `GET /v1/kyc/sessions/{sessionId}` confirms the status `cancelled_by_user` but does NOT return `cancelledAt` or `cancelReason`; those are delivered only in this webhook.\n**Billing.** A cancelled session is never billed as a verification: a cancel creates no verification request and no spend reservation, and never records the `kyc.verification` meter (that meter is recorded only at submit-time spend admission). Only the request-level `endpoint.collect.request` count applies, as for every hosted session call.\nRate limits: a per-IP limit, then a per-session limit — the same as `session-progress`.",
        "security": [
          {
            "SessionTokenAuth": []
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/KycSessionCancelRequest"
              },
              "example": {
                "reason": "not_now"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The session is `cancelled_by_user` — either this call cancelled it or it was already cancelled (idempotent replay; the original `cancelledAt` and `cancelReason` are returned).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KycSessionCancelResponse"
                },
                "example": {
                  "ok": true,
                  "status": "cancelled_by_user",
                  "cancelledAt": 1768434600000,
                  "cancelReason": "not_now",
                  "requestId": "req-test"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request` — invalid body, or `reason` outside the closed enum.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "401": {
            "description": "`invalid_session` — the session token is invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_session",
                  "requestId": "req-test"
                }
              }
            }
          },
          "403": {
            "description": "`origin_not_allowed` — missing or disallowed `Origin` (same origin enforcement as every other hosted route).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "origin_not_allowed",
                  "requestId": "req-test"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/GatedNotFound"
          },
          "409": {
            "description": "`session_not_cancellable` — the session is already `verifying`, `completed`, `unverified`, `error`, or `review_pending`; `status` names which.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KycSessionNotCancellableError"
                },
                "example": {
                  "error": "session_not_cancellable",
                  "status": "verifying",
                  "requestId": "req-test"
                }
              }
            }
          },
          "410": {
            "$ref": "#/components/responses/SessionExpired"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`invalid_request` — an unexpected internal fault while handling the cancel (any uncaught error in the handler). The body is the same `{error: invalid_request, requestId}` envelope as a `400`, so clients MUST key off the status code, not the error string, to tell the two apart. The session is not reported as cancelled; it is safe to retry the call (cancel is idempotent).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/kyc/session-submit": {
      "post": {
        "operationId": "kycSessionSubmit",
        "tags": [
          "KYC Hosted Sessions"
        ],
        "summary": "Submit the hosted session for verification (browser-facing, one-shot)",
        "description": "Drives the SAME `handleVerifyAction` pipeline `POST /v1/kyc/verify` uses, under the session's own tenant, with a server-derived payload (evidence object ids resolved exclusively from this session's own finalized evidence — a browser can never substitute its own payload fields). Single-use: a lost single-use claim on a concurrent resubmit returns `verify_gate_consumed`, distinct from a stale replay (`session_not_submittable`). See the closed `SUBMIT REFUSAL CODES` table below — hardened 2026-09-13 (D8b) so every pre-verification failure returns a distinct, actionable code instead of a shared `invalid_request`.\n**Email verification.** When the session's effective email-verification mode is `required` and the customer has not verified an address, the submit is refused with `409 email_verification_required`; the session stays open and can be submitted once the address is verified. Only possible while hosted email verification is enabled for the platform.\n**Noxtica Verification ID.** When the Noxtica Verification ID (NVID) is enabled for the platform, a `200` response also carries `nvid` — the session's NVID when the outcome is positive (`completed` or `review_pending`), otherwise `null`. The key is absent while the feature is not enabled.",
        "security": [
          {
            "SessionTokenAuth": []
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "Optional supplemental payload; the four pipeline-critical fields (operation, jurisdiction, evidenceObjectIds, subject, policy) are always server-derived and cannot be overridden by the caller."
              },
              "example": {}
            }
          }
        },
        "responses": {
          "200": {
            "description": "A resolved verify attempt (verified, unverified, or review_pending).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KycVerifyResponse"
                },
                "example": {
                  "ok": true,
                  "verdict": "verified",
                  "verificationLevel": "verified",
                  "reasonCodes": [
                    "provider_timeout"
                  ],
                  "verificationId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                  "requestId": "req-test",
                  "legalBasisRef": "example-legalBasisRef",
                  "nfcAssurance": {},
                  "deviceTrust": {}
                }
              }
            }
          },
          "400": {
            "description": "`idempotency_key_invalid` or `payload_invalid` — both new distinct codes as of 2026-09-13.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "403": {
            "description": "Missing/disallowed Origin, or an invalid/expired session token.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/GatedNotFound"
          },
          "409": {
            "description": "`session_not_submittable` (already terminal/mid-flight), `verify_gate_consumed` (NEW 2026-09-13 — lost the single-use race), or `email_verification_required` (NEW 2026-10-01 — the session's effective email-verification mode is `required` and no address has been verified yet).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "410": {
            "$ref": "#/components/responses/SessionExpiredOrCancelled"
          },
          "429": {
            "description": "`session_rate_limited` (the per-session budget, NEW 2026-09-13, distinct from the dispatcher-level 429 below) or the per-IP hosted-page limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "503": {
            "description": "`nonce_mint_unavailable` (NEW), `submit_internal_error` (NEW), `hosted_verify_not_configured`, or `kyc_legal_basis_receipt_unavailable`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/kyc/session-verification-id/email": {
      "post": {
        "operationId": "kycSessionVerificationIdEmail",
        "tags": [
          "KYC Hosted Sessions"
        ],
        "summary": "Email the person their Noxtica Verification ID (browser-facing, optional, consented)",
        "description": "Called by the hosted verification page when the person, on the final screen, asks Noxtica to email them their Noxtica Verification ID (NVID) and its public status link. Optional and independent of the verification outcome. **The person's explicit consent is required** (`consent.version` `nvid-email-v1`, `consent.accepted` `true`; the hosted checkbox is unticked by default). Noxtica — not the tenant — is the controller for this address: it is sealed (AES-256-GCM) at rest, used only to send this email, kept only with the verification record, never returned by any API and never disclosed to the tenant.\nOnly available while the NVID feature is enabled for the platform; otherwise the byte-identical gated `404`. Requires an issued, non-revoked NVID on the session (`409 verification_id_unavailable` otherwise). Limits: per-session, per-IP and per-address limiters, at most 3 sends per session from the hosted page, at least 60 seconds between sends (`429 rate_limited`).",
        "security": [
          {
            "SessionTokenAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/KycVerificationIdEmailRequest"
              },
              "example": {
                "email": "jane.doe@example.com",
                "locale": "en",
                "consent": {
                  "version": "nvid-email-v1",
                  "accepted": true
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The email was accepted for delivery.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    }
                  }
                },
                "example": {
                  "ok": true
                }
              }
            }
          },
          "400": {
            "description": "`invalid_email` or `consent_required`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "consent_required",
                  "requestId": "req-test"
                }
              }
            }
          },
          "403": {
            "description": "Missing/disallowed Origin, or an invalid/expired session token.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "origin_not_allowed",
                  "requestId": "req-test"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/GatedNotFound"
          },
          "409": {
            "description": "`verification_id_unavailable` — the session has no NVID, or it was revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "verification_id_unavailable",
                  "requestId": "req-test"
                }
              }
            }
          },
          "410": {
            "$ref": "#/components/responses/SessionExpiredOrCancelled"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "502": {
            "description": "`email_send_failed` — the provider refused or failed; the send slot is released.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "email_send_failed",
                  "requestId": "req-test"
                }
              }
            }
          },
          "503": {
            "description": "`email_unavailable` — the address cannot be sealed right now; nothing was stored.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "email_unavailable",
                  "requestId": "req-test"
                }
              }
            }
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/kyc/session-email/send": {
      "post": {
        "operationId": "kycSessionEmailSend",
        "tags": [
          "KYC Hosted Sessions"
        ],
        "summary": "Send the email-verification link for the address the customer typed (browser-facing)",
        "description": "Called by the hosted verification page, never by a tenant backend. Available only while hosted email verification is enabled for the platform AND the session's effective `emailVerification` mode (fixed at mint) is `optional` or `required`; otherwise the byte-identical gated `404` (platform off) or `409 email_verification_not_enabled` (mode `off`). Sends one confirmation link to the address; the link is valid for 30 minutes or until the session ends, whichever is sooner. Opening the link changes nothing: the customer must press the button on the page it opens, because mail gateways prefetch links.\nLimits per session: at most 5 accepted sends, at least 60 seconds between sends (`429 cooldown` with `retryAfterSec`, `429 send_limit_reached`), no send with less than 60 seconds of session left (`409 session_expiring`). Per client IP 20 sends an hour and per address 5 sends an hour (`429 Rate limit exceeded`). A provider failure rolls the send back (`502 email_send_failed`) so an outage does not spend the customer's quota. The response carries the masked address only.",
        "security": [
          {
            "SessionTokenAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "maxLength": 254,
                    "description": "The address to verify (normalised server-side)."
                  },
                  "locale": {
                    "type": "string",
                    "description": "One of the supported UI locales; the email is rendered in it (an unsupported value falls back to `en`)."
                  }
                }
              },
              "example": {
                "email": "jane.doe@example.com",
                "locale": "en"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The link was sent.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KycEmailVerificationStateEnvelope"
                },
                "example": {
                  "emailVerification": {
                    "mode": "required",
                    "email": "j***@example.com",
                    "verified": false,
                    "verifiedAt": null,
                    "expiresAt": 1790764000000,
                    "resendAvailableAt": 1790762260000,
                    "sendsRemaining": 4
                  },
                  "requestId": "req-test"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_email`, or `invalid_request` (unreadable body).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_email",
                  "requestId": "req-test"
                }
              }
            }
          },
          "401": {
            "description": "`invalid_session` — no session bearer, or one that does not resolve to a session.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_session",
                  "requestId": "req-test"
                }
              }
            }
          },
          "403": {
            "description": "Missing or disallowed `Origin`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "origin_not_allowed",
                  "requestId": "req-test"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/GatedNotFound"
          },
          "409": {
            "description": "`email_verification_not_enabled` (effective mode `off`), `already_verified` (this address is already confirmed; the body carries the current `emailVerification` state), `session_expiring` (under 60 seconds left), or `session_not_editable` (the session is past capture; the body carries its `status`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "email_verification_not_enabled",
                  "requestId": "req-test"
                }
              }
            }
          },
          "410": {
            "$ref": "#/components/responses/SessionExpiredOrCancelled"
          },
          "413": {
            "$ref": "#/components/responses/BodyTooLarge"
          },
          "429": {
            "description": "`cooldown` (with `retryAfterSec`), `send_limit_reached`, or `Rate limit exceeded` (per-session, per-IP or per-address bucket; `retryAfter`). `Retry-After` is sent for the cooldown and rate-limit cases.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "cooldown",
                  "retryAfterSec": 42,
                  "requestId": "req-test"
                }
              }
            }
          },
          "502": {
            "description": "`email_send_failed` — the mail provider refused or failed; the send was rolled back.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "email_send_failed",
                  "requestId": "req-test"
                }
              }
            }
          },
          "503": {
            "description": "`hosted_verify_not_configured`, `session_backend_unavailable`, or `invalid_request` (a transient lock or database fault); retry after the `Retry-After` seconds.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/kyc/session-email/status": {
      "get": {
        "operationId": "kycSessionEmailStatus",
        "tags": [
          "KYC Hosted Sessions"
        ],
        "summary": "Poll the email-verification state (browser-facing)",
        "description": "Called by the hosted verification page while the customer is in their mail app; it builds no snapshot, just the `emailVerification` state (masked address). Same availability as `POST /v1/kyc/session-email/send`: the byte-identical gated `404` while the platform has the feature off, `409 email_verification_not_enabled` for a session whose mode is `off`.",
        "security": [
          {
            "SessionTokenAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "The current state.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KycEmailVerificationStateEnvelope"
                },
                "example": {
                  "emailVerification": {
                    "mode": "optional",
                    "email": null,
                    "verified": false,
                    "verifiedAt": null,
                    "expiresAt": null,
                    "resendAvailableAt": null,
                    "sendsRemaining": 5
                  },
                  "requestId": "req-test"
                }
              }
            }
          },
          "401": {
            "description": "`invalid_session`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_session",
                  "requestId": "req-test"
                }
              }
            }
          },
          "403": {
            "description": "Missing or disallowed `Origin`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "origin_not_allowed",
                  "requestId": "req-test"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/GatedNotFound"
          },
          "409": {
            "description": "`email_verification_not_enabled` — the session's effective mode is `off`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "email_verification_not_enabled",
                  "requestId": "req-test"
                }
              }
            }
          },
          "410": {
            "$ref": "#/components/responses/SessionExpiredOrCancelled"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`session_backend_unavailable` or `invalid_request` — transient; retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/kyc/email-verification/confirm": {
      "post": {
        "operationId": "kycEmailVerificationConfirm",
        "tags": [
          "KYC Hosted Sessions"
        ],
        "summary": "Confirm the emailed link (browser-facing, link token is the credential)",
        "description": "Called by the page the emailed link opens, when the customer presses its one button. The link token (`kyev.<tenant>.<secret>`, 256-bit) is the only credential: no session bearer is read or accepted, and no session token is returned. Single use. A malformed, unknown, already used, expired, wrong-tenant or session-ended token all answer the identical `400 invalid_or_expired` (no oracle). The `Origin` must be on the hosted-verification allow-list. Per client IP 30 confirmations per 10 minutes. Available only while hosted email verification is enabled for the platform; otherwise the byte-identical gated `404`.",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "token"
                ],
                "properties": {
                  "token": {
                    "type": "string",
                    "maxLength": 512,
                    "description": "The link token, `kyev.<tenant>.<secret>`."
                  }
                }
              },
              "example": {
                "token": "kyev.tenant_42.q3JkT0vN8mYb1xW6cE4aZ7uP2sH9dLfR5gKiA0oXyUw"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The address is now verified for that session.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "requestId"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "requestId": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "requestId": "req-test"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_or_expired` (every token problem), or `invalid_request` (unreadable body).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_or_expired",
                  "requestId": "req-test"
                }
              }
            }
          },
          "403": {
            "description": "Missing or disallowed `Origin`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "origin_not_allowed",
                  "requestId": "req-test"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/GatedNotFound"
          },
          "413": {
            "$ref": "#/components/responses/BodyTooLarge"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`temporarily_unavailable` — transient fault; retry after `Retry-After` seconds.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "temporarily_unavailable",
                  "requestId": "req-test"
                }
              }
            }
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/kyc/verification-status": {
      "get": {
        "operationId": "kycVerificationIdStatus",
        "tags": [
          "KYC Hosted Sessions"
        ],
        "summary": "Read the public status of a Noxtica Verification ID (public, no authentication)",
        "description": "Public lookup behind the status link `https://verify.<env>/v/<NVID>` that a person can share. **No bearer token.** Returns only the status of the ID, its dates and the display name of the business that requested the verification — never a name, document data, image, email address or tenant identifier. An NVID confirms *status for a business*, not identity, and is **not a credential**: it cannot be used to sign in or to skip a verification.\n`status` is `revoked` (a Backoffice revocation; wins over everything), `pending` (the verification awaits a review decision), `expired` (365 days after completion) or `verified`. An unknown, erased or malformed ID — including one whose check symbol is wrong — answers the **same** `404 not_found` (no existence oracle). The `Origin` must be on the hosted-verification allow-list (`403 origin_not_allowed`); per-IP limit 60 requests per 60 seconds (`429`). Responses are `Cache-Control: no-store`. Only available while the NVID feature is enabled for the platform; otherwise the byte-identical gated `404`.",
        "security": [],
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "description": "The NVID, canonical form `NVID-XXXX-XXXX-XXXX-XXXX` (the collector also accepts the lower-case, unhyphenated and `O`/`I`/`L`-confusable spellings).",
            "schema": {
              "type": "string",
              "example": "NVID-7K3M-Q9XA-T2RW-4HZD"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The ID's public status.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "example": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KycVerificationIdStatusResponse"
                },
                "example": {
                  "ok": true,
                  "verification": {
                    "id": "NVID-7K3M-Q9XA-T2RW-4HZD",
                    "status": "verified",
                    "verifiedAt": 1790762445000,
                    "expiresAt": 1822298445000,
                    "revokedAt": null,
                    "requestedBy": "Example Bank"
                  }
                }
              }
            }
          },
          "403": {
            "description": "Missing or disallowed `Origin`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "origin_not_allowed",
                  "requestId": "req-test"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — unknown, erased or malformed ID (identical bodies), or the feature is not enabled for the platform (the gated `404` shape).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "string",
                      "enum": [
                        "not_found"
                      ]
                    }
                  }
                },
                "example": {
                  "ok": false,
                  "error": "not_found"
                }
              }
            }
          },
          "429": {
            "description": "Per-IP limit exceeded (60 requests per 60 seconds). `Retry-After` carries the seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error",
                    "retryAfter"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "string",
                      "enum": [
                        "rate_limited"
                      ]
                    },
                    "retryAfter": {
                      "type": "integer"
                    }
                  }
                },
                "example": {
                  "ok": false,
                  "error": "rate_limited",
                  "retryAfter": 12
                }
              }
            }
          },
          "503": {
            "description": "Temporarily unavailable; retry after `Retry-After` seconds (2).",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "error"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "error": {
                      "type": "string",
                      "enum": [
                        "temporarily_unavailable"
                      ]
                    }
                  }
                },
                "example": {
                  "ok": false,
                  "error": "temporarily_unavailable"
                }
              }
            }
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/kyc/session-evidence/handle": {
      "post": {
        "operationId": "kycSessionEvidenceHandle",
        "tags": [
          "KYC Hosted Sessions"
        ],
        "summary": "Mint an evidence-upload handle (browser-facing)",
        "description": "Token-authenticated sibling of `POST /v1/kyc/evidence/handle`, delegating to the same evidence pipeline — no parallel evidence store.",
        "security": [
          {
            "SessionTokenAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "Same shape as the S2S evidence/handle body, minus verificationId/tenant fields (resolved from the session)."
              },
              "example": {}
            }
          }
        },
        "responses": {
          "200": {
            "description": "Handle minted.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Same envelope as POST /v1/kyc/evidence/handle."
                },
                "example": {}
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "403": {
            "description": "Missing/disallowed Origin, or an invalid/expired session token.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/GatedNotFound"
          },
          "410": {
            "$ref": "#/components/responses/SessionExpiredOrCancelled"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/kyc/session-evidence/finalize": {
      "post": {
        "operationId": "kycSessionEvidenceFinalize",
        "tags": [
          "KYC Hosted Sessions"
        ],
        "summary": "Upload sealed ciphertext and finalize (browser-facing)",
        "description": "Token-authenticated sibling of `POST /v1/kyc/evidence/finalize`.",
        "security": [
          {
            "SessionTokenAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "Same shape as the S2S evidence/finalize body."
              },
              "example": {}
            }
          }
        },
        "responses": {
          "200": {
            "description": "Terminal inspection outcome.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Same envelope as POST /v1/kyc/evidence/finalize."
                },
                "example": {}
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/InvalidRequest"
          },
          "403": {
            "description": "Missing/disallowed Origin, an invalid/expired session token, or a failed handle verification.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/GatedNotFound"
          },
          "410": {
            "$ref": "#/components/responses/SessionExpiredOrCancelled"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/kyc/erasure/self-request": {
      "post": {
        "operationId": "kycErasureSelfRequest",
        "tags": [
          "KYC Compliance"
        ],
        "summary": "Create a right-to-erasure request for an attested subject",
        "description": "Device-callable FR-15 erasure intake. The subject is resolved server-side from an opaque `attestationId` — a caller can never supply a `subjectId` directly (no cross-subject erasure oracle). Always resolves 200; a resolution miss, an inactive subject, or an infra fault all collapse to the SAME `{ok:true, requested:false, status:'subject_not_attested'}` shape.",
        "security": [
          {
            "ApiKeyAuth": [
              "write:identity"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "attestationId"
                ],
                "properties": {
                  "attestationId": {
                    "type": "string"
                  }
                }
              },
              "example": {
                "attestationId": "att_9c6b2f7e4a3d4c8e9f1a2b3c4d5e6f70"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Always 200 (fail-closed discipline).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "requested": {
                      "type": "boolean"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "subject_not_attested",
                        "requested",
                        "erasure_request_failed"
                      ]
                    },
                    "requestId": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "requested": true,
                  "status": "subject_not_attested",
                  "requestId": "req-test"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/ScopeForbidden"
          },
          "404": {
            "$ref": "#/components/responses/GatedNotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/kyc/activate": {
      "post": {
        "operationId": "kycActivate",
        "tags": [
          "KYC Compliance"
        ],
        "summary": "Transactionally activate a proofed-unbound mobile capability",
        "description": "Composes a signed attestation projection, an atomic edge consent receipt, and a typed device-identity proof into one transactional activation. Two opaque references only (`attestationId`, `receiptId`) — never a `subjectId` or `tenantId` (both are resolved server-side). Available only when mobile activation is enabled for your organisation (a separate enablement from `/v1/kyc/verify`); otherwise the route answers the `GatedNotFound` 404.",
        "security": [
          {
            "ApiKeyAuth": [
              "write:identity"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "attestationId",
                  "receiptId"
                ],
                "properties": {
                  "attestationId": {
                    "type": "string"
                  },
                  "receiptId": {
                    "type": "string"
                  }
                }
              },
              "example": {
                "attestationId": "att_9c6b2f7e4a3d4c8e9f1a2b3c4d5e6f70",
                "receiptId": "receipt_2f6a8b3c9d4e5f60718293a4b5c6d7e8"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Always 200 (fail-closed discipline) — a false `activated:true` is never returned.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "activated": {
                      "type": "boolean"
                    },
                    "reason": {
                      "type": "string",
                      "description": "Present when activated is false (e.g. an unresolvable/foreign/stale attestation or receipt)."
                    },
                    "capability": {
                      "type": "object",
                      "description": "Present only when activated is true.",
                      "properties": {
                        "proofStatus": {
                          "type": "string",
                          "enum": [
                            "proofed_unbound"
                          ]
                        },
                        "verificationLevel": {
                          "type": "string",
                          "enum": [
                            "verified",
                            "partial",
                            "unverified",
                            "inconclusive"
                          ]
                        },
                        "receiptId": {
                          "type": "string"
                        },
                        "activatedAt": {
                          "type": "integer"
                        }
                      }
                    },
                    "requestId": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "activated": true,
                  "reason": "user_requested",
                  "capability": {
                    "proofStatus": "proofed_unbound",
                    "verificationLevel": "verified",
                    "receiptId": "receipt_2f6a8b3c9d4e5f60718293a4b5c6d7e8",
                    "activatedAt": 1
                  },
                  "requestId": "req-test"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/ScopeForbidden"
          },
          "404": {
            "$ref": "#/components/responses/GatedNotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/kym/transactions": {
      "post": {
        "operationId": "kymTransactionsReport",
        "tags": [
          "KYM"
        ],
        "summary": "Report one observed merchant transaction signal",
        "description": "Notify-only. Records exactly one transaction signal that feeds scheduled alert-rule evaluation; this endpoint never calls a payment or execution API. The target `caseId` must already exist under KYM monitoring (created in the Backoffice KYB/KYM case surface).",
        "security": [
          {
            "ApiKeyAuth": [
              "write:kym"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "caseId",
                  "idempotencyKey",
                  "amountMinor",
                  "currency",
                  "occurredAt"
                ],
                "properties": {
                  "caseId": {
                    "type": "string",
                    "maxLength": 512
                  },
                  "idempotencyKey": {
                    "type": "string",
                    "maxLength": 255
                  },
                  "amountMinor": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "Amount in the currency's minor unit (e.g. cents)."
                  },
                  "currency": {
                    "type": "string",
                    "pattern": "^[A-Z]{3}$",
                    "example": "USD"
                  },
                  "counterpartyRef": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "occurredAt": {
                    "type": "string",
                    "format": "date-time"
                  }
                }
              },
              "example": {
                "caseId": "example-caseId",
                "idempotencyKey": "example-idempotencyKey",
                "amountMinor": 0,
                "currency": "USD",
                "counterpartyRef": "example-counterpartyRef",
                "occurredAt": "2026-09-13T12:00:00.000Z"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "A replayed idempotencyKey — the original row (deduplicated).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KymTransactionResponse"
                },
                "example": {
                  "ok": true,
                  "eventId": "evt_3c9b2f7e4a3d4c8e9f1a2b3c4d5e6f70",
                  "deduplicated": false,
                  "requestId": "req-test"
                }
              }
            }
          },
          "201": {
            "description": "A new transaction-event row was recorded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KymTransactionResponse"
                },
                "example": {
                  "ok": true,
                  "eventId": "evt_3c9b2f7e4a3d4c8e9f1a2b3c4d5e6f70",
                  "deduplicated": false,
                  "requestId": "req-test"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_case_id` / `invalid_idempotency_key` / `invalid_amount` / `invalid_currency` / `invalid_occurred_at`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/ScopeForbidden"
          },
          "404": {
            "description": "The byte-identical gated-route 404, OR `case_not_found` (the caseId does not exist for this tenant).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "`write_failed` — a persistence fault.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/api/mcp": {
      "post": {
        "operationId": "mcpJsonRpc",
        "tags": [
          "MCP Server"
        ],
        "summary": "Send one MCP JSON-RPC request",
        "description": "Sends one JSON-RPC 2.0 request and returns one JSON-RPC 2.0 response. Set\n`Content-Type: application/json`. Notifications and batches are not supported: send one\nrequest object with a `method` and, for calls that expect an answer, an `id`.\n\nThe HTTP status is `200` for every JSON-RPC outcome, including errors, except for the\ntransport failures `401`, `404`, `429` and `500`.",
        "security": [
          {
            "McpTokenAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/JsonRpcRequest"
              },
              "examples": {
                "toolsList": {
                  "summary": "List the tools this token may call",
                  "value": {
                    "jsonrpc": "2.0",
                    "id": 1,
                    "method": "tools/list"
                  }
                },
                "toolsCall": {
                  "summary": "Call a tool",
                  "value": {
                    "jsonrpc": "2.0",
                    "id": 2,
                    "method": "tools/call",
                    "params": {
                      "name": "list_alerts",
                      "arguments": {
                        "limit": 25
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "A JSON-RPC response: `result` on success or `error` on failure (the HTTP status is `200` in both cases). With streamable transport negotiated and `Accept: text/event-stream`, the same object is sent as one `text/event-stream` `message` event.",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-RateLimit-Bucket": {
                "$ref": "#/components/headers/RateLimitBucket"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonRpcResponse"
                },
                "examples": {
                  "toolsCallResult": {
                    "summary": "A successful tool call",
                    "value": {
                      "jsonrpc": "2.0",
                      "id": 2,
                      "result": {
                        "content": [
                          {
                            "type": "text",
                            "text": "{\"tool\":\"list_alerts\",\"data\":{\"entries\":[],\"count\":0}}"
                          }
                        ],
                        "isError": false
                      }
                    }
                  },
                  "scopeError": {
                    "summary": "The token's scopes do not allow the tool",
                    "value": {
                      "jsonrpc": "2.0",
                      "id": 2,
                      "error": {
                        "code": -32001,
                        "message": "Insufficient scope for this tool",
                        "data": {
                          "requiredScope": "alerts.read"
                        }
                      }
                    }
                  },
                  "parseError": {
                    "summary": "The body is not valid JSON",
                    "value": {
                      "jsonrpc": "2.0",
                      "id": null,
                      "error": {
                        "code": -32700,
                        "message": "Parse error"
                      }
                    }
                  }
                }
              },
              "text/event-stream": {
                "schema": {
                  "type": "string",
                  "description": "One `message` event whose data is the JSON-RPC response."
                }
              }
            }
          },
          "401": {
            "description": "`unauthorized` — the `Authorization` header is missing or the token is unknown, revoked or expired. The body is identical for every cause.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/McpHttpError"
                },
                "example": {
                  "error": "unauthorized"
                }
              }
            }
          },
          "404": {
            "description": "`not_found` — the MCP server is not enabled for this deployment; the body is the same as for a path that does not exist.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/McpHttpError"
                },
                "example": {
                  "error": "not_found"
                }
              }
            }
          },
          "429": {
            "description": "`rate_limited` — the token exceeded its request limit. Wait `Retry-After` seconds.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the token may call again."
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              },
              "X-RateLimit-Bucket": {
                "$ref": "#/components/headers/RateLimitBucket"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/McpHttpError"
                },
                "example": {
                  "error": "rate_limited"
                }
              }
            }
          },
          "500": {
            "description": "`internal_error` — an unexpected server error. Retry with backoff.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/McpHttpError"
                },
                "example": {
                  "error": "internal_error"
                }
              }
            }
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://backoffice.noxtica.com",
          "description": "Production"
        }
      ]
    },
    "/pulse/v1/tenant/subjects/{subject}": {
      "get": {
        "tags": [
          "Tenant"
        ],
        "operationId": "pulseTenantSubjectStatus",
        "summary": "Status of one player (pseudonymous subject) of the calling tenant",
        "description": "Server-to-server, scope `read:pulse`. `subject` is a `psub_…` enrolment pseudonym, the pairwise link subject `plnk_…` or the tenant's own `externalUserId` (both resolve ONLY through an ACTIVE link: after an unlink they answer `404 subject_not_found`; an `externalUserId` linked in several applications is `409 ambiguous_subject` unless `?appId=` names one). A subject resolved through a link shows only the scopes the player consented to (`status`: `enrolled`/`revokedAt`/`reasonCode`; `attestation_level`: `deviceAttestationLevel`; `last_seen`: `lastSeen`; `open_signals`: `openSignals`) and echoes them in `scopes`. The tenant is always the key's tenant: unknown subjects and other tenants' subjects are the same `404 subject_not_found`. The answer carries no account PII and no enrolment, device or key identifier. A revoked subject answers `enrolled: false` with `revokedAt` and `reasonCode`. `openSignals` are the subject's open detections (`open`, `under_review`), newest first, at most 50, with tenant-safe fields only; `[]` when there are none. `Cache-Control: no-store`. Times are epoch milliseconds.",
        "security": [
          {
            "tenantKey": [
              "read:pulse"
            ]
          }
        ],
        "parameters": [
          {
            "name": "subject",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 256
            },
            "example": "psub_01M4GW6CR553W8AAWXEG17RDJW"
          },
          {
            "$ref": "#/components/parameters/TenantAppId"
          }
        ],
        "responses": {
          "200": {
            "description": "The subject's status.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantSubjectStatus"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_subject` (undecodable, control characters or longer than 256).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "`missing_api_key` or `invalid_api_key` (malformed, unknown, revoked, or a device token). `WWW-Authenticate: Bearer realm=\"pulse-tenant\"`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` (the key lacks `read:pulse`) or `tenant_not_armed` (the tenant is not active and Pulse-enabled).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "`subject_not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "409": {
            "description": "`ambiguous_subject` — the `externalUserId` is linked in several applications: pass `?appId=`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/pulse_RateLimited"
          },
          "503": {
            "description": "`tenant_auth_unavailable` or `rate_limiter_unavailable` (fail closed).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          }
        }
      },
      "servers": [
        {
          "url": "https://pulse.noxtica.com",
          "description": "Production (not yet deployed)"
        }
      ]
    },
    "/pulse/v1/tenant/decisions": {
      "get": {
        "tags": [
          "Tenant"
        ],
        "operationId": "pulseTenantListDecisions",
        "summary": "List the tenant's response decisions (audit), newest first",
        "description": "Server-to-server, scope `read:pulse`. Every response action the device executed, suppressed or dry-ran under the tenant's signed profile, with its reason code, the outcome of record, the linked detection's review status and appeal state, and the hint state. Keyset-paged (`cursor` from `nextCursor`). Pseudonyms (`psub`, `deviceRef`) and closed codes only: no account id, e-mail, enrolment id, evidence, profile hash or staff identity. `subject` resolves like the subject status; for a linked subject the player must have granted `open_signals` (`403 scope_not_granted`). `Cache-Control: no-store`.",
        "security": [
          {
            "tenantKey": [
              "read:pulse"
            ]
          }
        ],
        "parameters": [
          {
            "name": "app_id",
            "in": "query",
            "schema": {
              "type": "string",
              "pattern": "^[a-z0-9][a-z0-9-]{0,62}$"
            }
          },
          {
            "name": "device_ref",
            "in": "query",
            "description": "The `pdrf_` pseudonym of the device (server-side filter: the page and `nextCursor` only walk this device's decisions).",
            "schema": {
              "type": "string",
              "pattern": "^pdrf_[0-9A-HJKMNP-TV-Z]{26}$"
            }
          },
          {
            "name": "severity",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "low",
                "medium",
                "high",
                "critical"
              ]
            }
          },
          {
            "name": "subject",
            "in": "query",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 256
            }
          },
          {
            "name": "outcome",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/ResponseOutcome"
            }
          },
          {
            "name": "action",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/ResponseAction"
            }
          },
          {
            "name": "reason_code",
            "in": "query",
            "schema": {
              "type": "string",
              "pattern": "^[A-Z]{3}-[0-9]{3}$"
            }
          },
          {
            "name": "rule_id",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 64
            }
          },
          {
            "name": "hint_state",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "active",
                "expired",
                "reversed",
                "none"
              ]
            }
          },
          {
            "name": "detection_id",
            "in": "query",
            "schema": {
              "type": "string",
              "pattern": "^pdet_[0-9A-HJKMNP-TV-Z]{26}$"
            }
          },
          {
            "name": "from",
            "in": "query",
            "description": "Epoch ms (inclusive) of the device decision.",
            "schema": {
              "type": "integer",
              "format": "int64",
              "minimum": 1
            }
          },
          {
            "name": "to",
            "in": "query",
            "description": "Epoch ms (exclusive).",
            "schema": {
              "type": "integer",
              "format": "int64",
              "minimum": 1
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 96
            }
          }
        ],
        "responses": {
          "200": {
            "description": "One page of decisions.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantDecisionList"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request` (a malformed filter) or `invalid_cursor`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "`missing_api_key` or `invalid_api_key` (a device token is never accepted).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope`, `tenant_not_armed` or `scope_not_granted`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "`subject_not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/pulse_RateLimited"
          }
        }
      },
      "servers": [
        {
          "url": "https://pulse.noxtica.com",
          "description": "Production (not yet deployed)"
        }
      ]
    },
    "/pulse/v1/tenant/decisions/{id}": {
      "get": {
        "tags": [
          "Tenant"
        ],
        "operationId": "pulseTenantGetDecision",
        "summary": "One response decision",
        "description": "Scope `read:pulse`. `404 decision_not_found` for an unknown or another tenant's id (indistinguishable).",
        "security": [
          {
            "tenantKey": [
              "read:pulse"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^pact_[0-7][0-9A-HJKMNP-TV-Z]{25}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The decision.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantDecision"
                }
              }
            }
          },
          "401": {
            "description": "`missing_api_key` or `invalid_api_key`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` or `tenant_not_armed`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "`decision_not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/pulse_RateLimited"
          }
        }
      },
      "servers": [
        {
          "url": "https://pulse.noxtica.com",
          "description": "Production (not yet deployed)"
        }
      ]
    },
    "/pulse/v1/tenant/decisions/{id}/reverse": {
      "post": {
        "tags": [
          "Tenant"
        ],
        "operationId": "pulseTenantReverseDecision",
        "summary": "Withdraw an active response hint",
        "description": "Scope `write:pulse`. The tenant back end marks the decision's ACTIVE hint as handled or withdrawn, with a closed `reasonCode`. The reversal is an append-only audit event (actor = the API key id) and is announced by the `pulse.response.v1` webhook (transition `reversed`). Idempotent: an already reversed hint answers `200` and writes nothing. A decision without an active hint (a dry run, a suppressed action, an expired hint) is `409 hint_not_active`.",
        "security": [
          {
            "tenantKey": [
              "write:pulse"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^pact_[0-7][0-9A-HJKMNP-TV-Z]{25}$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "reasonCode"
                ],
                "properties": {
                  "reasonCode": {
                    "type": "string",
                    "enum": [
                      "handled",
                      "false_positive",
                      "account_verified",
                      "policy_exception",
                      "other"
                    ]
                  },
                  "note": {
                    "type": "string",
                    "maxLength": 500
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The decision with `hint.state` = `reversed`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantDecision"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "description": "`missing_api_key` or `invalid_api_key`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_scope` (needs `write:pulse`) or `tenant_not_armed`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "404": {
            "description": "`decision_not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "409": {
            "description": "`hint_not_active`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "415": {
            "$ref": "#/components/responses/ApiError"
          },
          "429": {
            "$ref": "#/components/responses/pulse_RateLimited"
          }
        }
      },
      "servers": [
        {
          "url": "https://pulse.noxtica.com",
          "description": "Production (not yet deployed)"
        }
      ]
    },
    "/pulse/v1/tenant/link-codes": {
      "post": {
        "tags": [
          "Tenant"
        ],
        "operationId": "pulseTenantCreateLinkCode",
        "summary": "Issue a one-time link code for one of the tenant's own users",
        "description": "Server-to-server, scope `write:pulse`. The tenant backend (a launcher, a game server) asks for a code for ITS user `externalUserId` in one of its applications and hands the returned `url` to that person. The code is shown once, valid 10 minutes, single use; only its SHA-256 is stored. The person opens the URL signed in to their Pulse account, sees the tenant, the application, the masked user id and the data the tenant will see, and approves (the link is the consent receipt) or denies. At most 5 unconsumed codes exist per (application, `externalUserId`) (`429 too_many_outstanding_codes`, `Retry-After: 600`); 30 codes per key per minute and 600 per tenant per hour (`429 rate_limited`). A user id that already has an active link in that application is `409 external_user_already_linked` (unlink it first). `Cache-Control: no-store`.",
        "security": [
          {
            "tenantKey": [
              "write:pulse"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TenantLinkCodeRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The code (shown ONCE).",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantLinkCode"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_parameter` / `missing_parameter` (empty, padded, control-character or over-long `externalUserId`; malformed `appId` or `locale`), or a non-JSON body.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/TenantUnauthorized"
          },
          "403": {
            "$ref": "#/components/responses/TenantForbidden"
          },
          "404": {
            "description": "`application_not_found` — not an active application of this tenant.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "409": {
            "description": "`external_user_already_linked`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "415": {
            "$ref": "#/components/responses/ApiError"
          },
          "429": {
            "$ref": "#/components/responses/pulse_RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/TenantUnavailable"
          }
        }
      },
      "servers": [
        {
          "url": "https://pulse.noxtica.com",
          "description": "Production (not yet deployed)"
        }
      ]
    },
    "/pulse/v1/tenant/links/{subject}": {
      "get": {
        "tags": [
          "Tenant"
        ],
        "operationId": "pulseTenantGetLink",
        "summary": "Read one link of the calling tenant",
        "description": "Scope `read:pulse`. `subject` is the pairwise `plnk_…` (resolves in EVERY state, so an unlink is observable as `state: unlinked` with `unlinkedBy`) or the tenant's own `externalUserId` (resolves only through its ACTIVE link; `409 ambiguous_subject` when it is linked in several applications unless `?appId=` names one). Another tenant's link, an unknown subject and an unlinked `externalUserId` are the same `404 subject_not_found`. The answer never carries an account id, e-mail, psub or device fact. `Cache-Control: no-store`.",
        "security": [
          {
            "tenantKey": [
              "read:pulse"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TenantLinkSubject"
          },
          {
            "$ref": "#/components/parameters/TenantAppId"
          }
        ],
        "responses": {
          "200": {
            "description": "The link.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantLink"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_subject` or `invalid_parameter` (malformed `appId`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/TenantUnauthorized"
          },
          "403": {
            "$ref": "#/components/responses/TenantForbidden"
          },
          "404": {
            "description": "`subject_not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "409": {
            "description": "`ambiguous_subject`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/pulse_RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/TenantUnavailable"
          }
        }
      },
      "delete": {
        "tags": [
          "Tenant"
        ],
        "operationId": "pulseTenantUnlink",
        "summary": "Unlink a player (tenant side)",
        "description": "Scope `write:pulse`. Ends the link (`unlinkedBy: tenant`): the player's enrolments of that application lose the binding, the link is audited, and a `pulse.enrolment.linked.v1` webhook (`transition: unlinked`) is queued in the same transaction. Idempotent: an already unlinked link answers `200` with `changed: false` and writes nothing. Same subject forms, `?appId=` rule and `404 subject_not_found` as `GET`. The player can link again with a new code; that creates a NEW `plnk_…` subject.",
        "security": [
          {
            "tenantKey": [
              "write:pulse"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/TenantLinkSubject"
          },
          {
            "$ref": "#/components/parameters/TenantAppId"
          }
        ],
        "responses": {
          "200": {
            "description": "The link after the call.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantLinkUnlinked"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_subject` or `invalid_parameter`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/TenantUnauthorized"
          },
          "403": {
            "$ref": "#/components/responses/TenantForbidden"
          },
          "404": {
            "description": "`subject_not_found`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "409": {
            "description": "`ambiguous_subject`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/pulse_RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/TenantUnavailable"
          }
        }
      },
      "servers": [
        {
          "url": "https://pulse.noxtica.com",
          "description": "Production (not yet deployed)"
        }
      ]
    },
    "/v1/device/{deviceId}": {
      "get": {
        "operationId": "v1GetDevice",
        "tags": [
          "Devices"
        ],
        "summary": "Look up a device by ID",
        "description": "Returns the current score and risk projection of one device — the `fingerprintId` your browser or mobile integration received — scoped to the calling organisation.\n\nThe route answers `404` with `{\"error\":\"Device not found\",\"deviceId\":\"...\",\"requestId\":\"...\"}` when the device is unknown, belongs to another organisation, or has not been seen within your organisation's configured retention window.\n\n- `reasonCodes` is the published, non-personal reason-code projection of the internal flags. It is an empty array unless reason-code output is enabled for your organisation, independently of the raw `flags` field.\n- `gpuAttestationTier` is masked: a stored `hardware` or `software` tier is reported as `attested` unless publication of the hardware attestation level is enabled for your organisation. `gpuVerified` is not masked and never asserts `hardware`.\n- `subscores` and `details` are the scorer's per-domain breakdown when present, otherwise `null`. `softwareSubfp`, `hardwareSubfp` and `environmentSubfp` are server-derived observational sub-fingerprints; they are `null` for devices recorded before those fields existed.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "read:device"
            ]
          }
        ],
        "parameters": [
          {
            "name": "deviceId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The `device_id` to look up (URL-decoded from the path segment)."
          }
        ],
        "responses": {
          "200": {
            "description": "The device's current score/risk projection.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "device"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "device": {
                      "type": "object",
                      "properties": {
                        "deviceId": {
                          "type": "string"
                        },
                        "domainId": {
                          "type": "string"
                        },
                        "score": {
                          "type": "number"
                        },
                        "riskLevel": {
                          "type": "string"
                        },
                        "confidence": {
                          "type": [
                            "number",
                            "null"
                          ]
                        },
                        "flags": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "reasonCodes": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          },
                          "description": "Empty unless reason-code output is enabled for your organisation."
                        },
                        "subscores": {
                          "type": [
                            "object",
                            "null"
                          ],
                          "additionalProperties": true
                        },
                        "details": {
                          "type": [
                            "object",
                            "null"
                          ],
                          "additionalProperties": true
                        },
                        "country": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "city": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "createdAt": {
                          "type": "string",
                          "format": "date-time"
                        },
                        "updatedAt": {
                          "type": "string",
                          "format": "date-time"
                        },
                        "lastSubmittedAt": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "format": "date-time"
                        },
                        "lastSeenAt": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "format": "date-time"
                        },
                        "gpuVerified": {
                          "type": "boolean"
                        },
                        "gpuAttestationTier": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "enum": [
                            "attested",
                            "suspicious",
                            "unavailable",
                            "failed",
                            "hardware",
                            "software"
                          ],
                          "description": "Masked unless publication of the hardware attestation level is enabled for your organisation; see description above."
                        },
                        "softwareSubfp": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "hardwareSubfp": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "environmentSubfp": {
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      }
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "device": {
                    "deviceId": "dev_7a2b9c4d1e6f3a8b5c2d9e4f7a1b6c3d",
                    "domainId": "dom_3f2a8c91d6e5f470",
                    "score": 1,
                    "riskLevel": "low",
                    "confidence": 1,
                    "flags": [
                      "example-flags"
                    ],
                    "reasonCodes": [
                      "example-reasonCodes"
                    ],
                    "subscores": {},
                    "details": {},
                    "country": "US",
                    "city": "Istanbul",
                    "createdAt": "2026-09-13T12:00:00.000Z",
                    "updatedAt": "2026-09-13T12:00:00.000Z",
                    "lastSubmittedAt": "2026-09-13T12:00:00.000Z",
                    "lastSeenAt": "2026-09-13T12:00:00.000Z",
                    "gpuVerified": true,
                    "gpuAttestationTier": "attested",
                    "softwareSubfp": "example-softwareSubfp",
                    "hardwareSubfp": "example-hardwareSubfp",
                    "environmentSubfp": "example-environmentSubfp"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Missing/empty `deviceId`, or the path segment failed URL-decoding.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/v1_InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/v1_ScopeForbidden"
          },
          "404": {
            "description": "`{ error: 'Device not found', deviceId, requestId }` — tenant projection inactive/missing OR the row is absent/outside the retention window.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "Device not found"
                      ]
                    },
                    "deviceId": {
                      "type": "string"
                    },
                    "requestId": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "error": "Device not found",
                  "deviceId": "dev_7a2b9c4d1e6f3a8b5c2d9e4f7a1b6c3d",
                  "requestId": "req-test"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/v1_RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/devices": {
      "get": {
        "operationId": "v1ListDevices",
        "tags": [
          "Devices"
        ],
        "summary": "List devices",
        "description": "Lists devices, most recently updated first, with filters and keyset pagination. `from` and `to` bound the range and may span at most 400 days. `source` selects real devices, synthetic devices (see the generator operations) or both; `all` merges both result sets by `(updated_at, device_id)` descending.\n\n`cursor` is opaque: pass the `nextCursor` of the previous page back unchanged and never construct one. `limit` defaults to 50 and is capped at 200.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "read:fingerprints"
            ]
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 200
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Opaque keyset cursor from a prior response's `nextCursor`."
          },
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Defaults to 400 days before now."
          },
          {
            "name": "to",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Defaults to now."
          },
          {
            "name": "domain_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "risk_level",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filter by risk level; the allowed set is deps-injected (`riskLevelFilterValues`)."
          },
          {
            "name": "source",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "real",
                "synthetic",
                "all"
              ],
              "default": "real"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of devices.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "devices",
                    "hasMore",
                    "nextCursor"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "devices": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "deviceId": {
                            "type": "string"
                          },
                          "domainId": {
                            "type": "string"
                          },
                          "score": {
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "riskLevel": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "flags": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "country": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "updatedAt": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "isSynthetic": {
                            "type": "boolean"
                          }
                        }
                      }
                    },
                    "hasMore": {
                      "type": "boolean"
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "devices": [
                    {
                      "deviceId": "dev_7a2b9c4d1e6f3a8b5c2d9e4f7a1b6c3d",
                      "domainId": "dom_3f2a8c91d6e5f470",
                      "score": 1,
                      "riskLevel": "low",
                      "flags": [
                        "example-flags"
                      ],
                      "country": "US",
                      "createdAt": "2026-09-13T12:00:00.000Z",
                      "updatedAt": "2026-09-13T12:00:00.000Z",
                      "isSynthetic": true
                    }
                  ],
                  "hasMore": true,
                  "nextCursor": "cursor_000123"
                }
              }
            }
          },
          "400": {
            "description": "`Invalid source`, `Invalid risk_level`, or `Invalid date range` (bad/inverted/over-400-day `from`/`to`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/v1_InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/v1_ScopeForbidden"
          },
          "429": {
            "$ref": "#/components/responses/v1_RateLimited"
          },
          "500": {
            "description": "`{ error: 'Failed to query devices', code: 'devices_list_query_failed' }` on a warehouse fault, or a generic internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/accounts/{accountHash}/devices": {
      "get": {
        "operationId": "v1ListAccountDevices",
        "tags": [
          "Devices"
        ],
        "summary": "List devices linked to an account",
        "description": "Lists the devices and agents linked to one of your end-user accounts, with their current score and risk only. `accountHash` must be the keyed 16-character lowercase-hex pseudonym your organisation already receives elsewhere (for example the `account_hash` filter of `GET /v1/events`); a raw account id is never accepted on this path.\n\nPagination is a keyset cursor over `(last_seen_at, id)` descending, with the same opaque cursor shape as `GET /v1/events`.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "read:fingerprints"
            ]
          }
        ],
        "parameters": [
          {
            "name": "accountHash",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[0-9a-f]{16}$"
            },
            "description": "The keyed 16-hex-lowercase account pseudonym."
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 200
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The account's linked device/agent history.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "accountHash",
                    "links",
                    "hasMore",
                    "nextCursor"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "accountHash": {
                      "type": "string"
                    },
                    "links": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "agentKeyid": {
                            "type": "string"
                          },
                          "agentHost": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "deviceId": {
                            "type": "string"
                          },
                          "domainId": {
                            "type": "string"
                          },
                          "firstSeenAt": {
                            "type": "integer",
                            "description": "Epoch ms."
                          },
                          "lastSeenAt": {
                            "type": "integer",
                            "description": "Epoch ms."
                          },
                          "seenCount": {
                            "type": "integer"
                          },
                          "deviceScore": {
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "deviceRiskLevel": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "deviceUpdatedAt": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        }
                      }
                    },
                    "hasMore": {
                      "type": "boolean"
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "accountHash": "a1b2c3d4e5f60718293a4b5c6d7e8f901a2b3c4d5e6f708192a3b4c5d6e7f89",
                  "links": [
                    {
                      "agentKeyid": "example-agentKeyid",
                      "agentHost": "example-agentHost",
                      "deviceId": "dev_7a2b9c4d1e6f3a8b5c2d9e4f7a1b6c3d",
                      "domainId": "dom_3f2a8c91d6e5f470",
                      "firstSeenAt": 1,
                      "lastSeenAt": 1,
                      "seenCount": 1,
                      "deviceScore": 1,
                      "deviceRiskLevel": "example-deviceRiskLevel",
                      "deviceUpdatedAt": "example-deviceUpdatedAt"
                    }
                  ],
                  "hasMore": true,
                  "nextCursor": "cursor_000123"
                }
              }
            }
          },
          "400": {
            "description": "`accountHash` fails the 16-hex-lowercase shape check.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/v1_InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/v1_ScopeForbidden"
          },
          "429": {
            "$ref": "#/components/responses/v1_RateLimited"
          },
          "500": {
            "description": "`{ error: 'Failed to query account devices', code: 'account_devices_query_failed' }` or a generic internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/events": {
      "get": {
        "operationId": "v1ListEvents",
        "tags": [
          "Events & Visits"
        ],
        "summary": "List scoring events",
        "description": "Lists scored events, newest first, with a keyset cursor over `(created_at, id)`. The optional `account_hash` filter (a keyed 16-character lowercase-hex pseudonym) applies to `source=real` only: synthetic events and the merged `all` view carry no `account_hash`.\n\n`reasonCodes` is the published reason-code projection of the event's internal flags; it is empty unless reason-code output is enabled for your organisation.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "read:events"
            ]
          }
        ],
        "parameters": [
          {
            "name": "device_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "to",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "domain_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "account_hash",
            "in": "query",
            "schema": {
              "type": "string",
              "pattern": "^[0-9a-f]{16}$"
            },
            "description": "Applied only when `source` resolves to `real`."
          },
          {
            "name": "source",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "real",
                "synthetic",
                "all"
              ],
              "default": "real"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 200
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of events.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "events",
                    "hasMore",
                    "nextCursor"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "events": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "deviceId": {
                            "type": "string"
                          },
                          "domainId": {
                            "type": "string"
                          },
                          "score": {
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "riskLevel": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "confidence": {
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "flags": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "reasonCodes": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "country": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "payloadUnavailable": {
                            "type": [
                              "boolean",
                              "null"
                            ]
                          },
                          "isSynthetic": {
                            "type": "boolean"
                          }
                        }
                      }
                    },
                    "hasMore": {
                      "type": "boolean"
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "events": [
                    {
                      "id": "example-id",
                      "deviceId": "dev_7a2b9c4d1e6f3a8b5c2d9e4f7a1b6c3d",
                      "domainId": "dom_3f2a8c91d6e5f470",
                      "score": 1,
                      "riskLevel": "low",
                      "confidence": 1,
                      "flags": [
                        "example-flags"
                      ],
                      "reasonCodes": [
                        "example-reasonCodes"
                      ],
                      "country": "US",
                      "createdAt": "2026-09-13T12:00:00.000Z",
                      "payloadUnavailable": true,
                      "isSynthetic": true
                    }
                  ],
                  "hasMore": true,
                  "nextCursor": "cursor_000123"
                }
              }
            }
          },
          "400": {
            "description": "`Invalid source`, or `account_hash` fails the 16-hex-lowercase shape check.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/v1_InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/v1_ScopeForbidden"
          },
          "429": {
            "$ref": "#/components/responses/v1_RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/visits": {
      "get": {
        "operationId": "v1ListVisits",
        "tags": [
          "Events & Visits"
        ],
        "summary": "List visits",
        "description": "Lists visit records, newest first, with a keyset cursor over `(created_at, id)`. Visits have no synthetic partition, so this route has no `source` filter. `meta` is the visit's own parsed JSON metadata and includes `external_user_id` when the submitting page set it.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "read:visits"
            ]
          }
        ],
        "parameters": [
          {
            "name": "device_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "to",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "domain_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "external_user_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 200
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of visits.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "visits",
                    "hasMore",
                    "nextCursor"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "visits": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "deviceId": {
                            "type": "string"
                          },
                          "domainId": {
                            "type": "string"
                          },
                          "country": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "city": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "meta": {
                            "type": "object",
                            "additionalProperties": true,
                            "description": "The row's own parsed JSON `meta` blob (e.g. `external_user_id`); shape is submitter-controlled and not locally validated."
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    },
                    "hasMore": {
                      "type": "boolean"
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "visits": [
                    {
                      "id": "example-id",
                      "deviceId": "dev_7a2b9c4d1e6f3a8b5c2d9e4f7a1b6c3d",
                      "domainId": "dom_3f2a8c91d6e5f470",
                      "country": "US",
                      "city": "Istanbul",
                      "meta": {},
                      "createdAt": "2026-09-13T12:00:00.000Z"
                    }
                  ],
                  "hasMore": true,
                  "nextCursor": "cursor_000123"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/v1_InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/v1_ScopeForbidden"
          },
          "429": {
            "$ref": "#/components/responses/v1_RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/exports/fingerprints": {
      "get": {
        "operationId": "v1ExportFingerprints",
        "tags": [
          "Exports"
        ],
        "summary": "Export fingerprints as CSV or JSON",
        "description": "Bulk-exports device fingerprint records for a date range. `from` and `to` are required and are validated for both shape and calendar (a malformed string or an impossible date such as `2026-02-30` is rejected) before being echoed into the CSV `Content-Disposition` filename.\n\nEach request returns at most a fixed maximum number of rows. A capped page sets `truncated: true` (JSON) or the `X-Noxtica-Export-Truncated: true` header (CSV) and an opaque keyset `next_cursor` (JSON) or `X-Noxtica-Export-Next-Cursor` header (CSV) over `(created_at, id)` descending; request the next page with that cursor.\n\n`reason_codes` is the published reason-code projection (empty unless reason-code output is enabled for your organisation) and is the last CSV column, so fixed-position consumers are unaffected.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "read:export"
            ]
          }
        ],
        "parameters": [
          {
            "name": "format",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "csv"
              ],
              "default": "json"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "REQUIRED. `YYYY-MM-DD`, `YYYY-MM-DD HH:MM:SS`, or ISO 8601 (optional ms/offset)."
          },
          {
            "name": "to",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "domain_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "source",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "real",
                "synthetic",
                "all"
              ],
              "default": "real"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Opaque keyset cursor from a prior response's `next_cursor`. Omit for page 1."
          }
        ],
        "responses": {
          "200": {
            "description": "The exported page, as a JSON envelope or a raw CSV body depending on `format`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "count",
                    "limit",
                    "truncated",
                    "from",
                    "to",
                    "fingerprints"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "count": {
                      "type": "integer"
                    },
                    "limit": {
                      "type": "integer"
                    },
                    "truncated": {
                      "type": "boolean"
                    },
                    "from": {
                      "type": "string"
                    },
                    "to": {
                      "type": "string"
                    },
                    "next_cursor": {
                      "type": "string"
                    },
                    "fingerprints": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "device_id": {
                            "type": "string"
                          },
                          "domain_id": {
                            "type": "string"
                          },
                          "score": {
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "risk_level": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "flags": {
                            "type": "string",
                            "description": "Semicolon-joined."
                          },
                          "reason_codes": {
                            "type": "string",
                            "description": "Semicolon-joined; empty unless reason-code output is enabled for your organisation."
                          },
                          "country": {
                            "type": "string"
                          },
                          "city": {
                            "type": "string"
                          },
                          "created_at": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "updated_at": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "is_synthetic": {
                            "type": "string",
                            "enum": [
                              "true",
                              "false"
                            ]
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "count": 1,
                  "limit": 1,
                  "truncated": true,
                  "from": "example-from",
                  "to": "example-to",
                  "next_cursor": "cursor_000123",
                  "fingerprints": [
                    {
                      "device_id": "dev_7a2b9c4d1e6f3a8b5c2d9e4f7a1b6c3d",
                      "domain_id": "dom_3f2a8c91d6e5f470",
                      "score": 1,
                      "risk_level": "low",
                      "flags": "example-flags",
                      "reason_codes": "example-reason_codes",
                      "country": "US",
                      "city": "Istanbul",
                      "created_at": "2026-09-13T12:00:00.000Z",
                      "updated_at": "2026-09-13T12:00:00.000Z",
                      "is_synthetic": "true"
                    }
                  ]
                }
              },
              "text/csv": {
                "schema": {
                  "type": "string"
                },
                "example": "example-v1ExportFingerprints"
              }
            },
            "headers": {
              "X-Noxtica-Export-Truncated": {
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              },
              "X-Noxtica-Export-Next-Cursor": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "`Invalid source`/`Invalid format`, missing `from`/`to`, or `from and to must be YYYY-MM-DD or ISO 8601 datetime values`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/v1_InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/v1_ScopeForbidden"
          },
          "429": {
            "$ref": "#/components/responses/v1_RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/exports/events": {
      "get": {
        "operationId": "v1ExportEvents",
        "tags": [
          "Exports"
        ],
        "summary": "Export events as CSV or JSON",
        "description": "Bulk-exports scored events for a date range. The contract is identical to `GET /v1/exports/fingerprints`: the same date validation, per-request row cap, and `truncated` / `next_cursor` pagination.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "read:export"
            ]
          }
        ],
        "parameters": [
          {
            "name": "format",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "csv"
              ],
              "default": "json"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "domain_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "source",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "real",
                "synthetic",
                "all"
              ],
              "default": "real"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The exported page, as a JSON envelope or a raw CSV body depending on `format`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "count",
                    "limit",
                    "truncated",
                    "from",
                    "to",
                    "events"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "count": {
                      "type": "integer"
                    },
                    "limit": {
                      "type": "integer"
                    },
                    "truncated": {
                      "type": "boolean"
                    },
                    "from": {
                      "type": "string"
                    },
                    "to": {
                      "type": "string"
                    },
                    "next_cursor": {
                      "type": "string"
                    },
                    "events": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "device_id": {
                            "type": "string"
                          },
                          "domain_id": {
                            "type": "string"
                          },
                          "score": {
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "risk_level": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "reason_codes": {
                            "type": "string",
                            "description": "Semicolon-joined; empty unless reason-code output is enabled for your organisation."
                          },
                          "country": {
                            "type": "string"
                          },
                          "created_at": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "is_synthetic": {
                            "type": "string",
                            "enum": [
                              "true",
                              "false"
                            ]
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "count": 1,
                  "limit": 1,
                  "truncated": true,
                  "from": "example-from",
                  "to": "example-to",
                  "next_cursor": "cursor_000123",
                  "events": [
                    {
                      "id": "example-id",
                      "device_id": "dev_7a2b9c4d1e6f3a8b5c2d9e4f7a1b6c3d",
                      "domain_id": "dom_3f2a8c91d6e5f470",
                      "score": 1,
                      "risk_level": "low",
                      "reason_codes": "example-reason_codes",
                      "country": "US",
                      "created_at": "2026-09-13T12:00:00.000Z",
                      "is_synthetic": "true"
                    }
                  ]
                }
              },
              "text/csv": {
                "schema": {
                  "type": "string"
                },
                "example": "example-v1ExportEvents"
              }
            },
            "headers": {
              "X-Noxtica-Export-Truncated": {
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              },
              "X-Noxtica-Export-Next-Cursor": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "`Invalid source`/`Invalid format`, missing `from`/`to`, or invalid date shape/calendar.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/v1_InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/v1_ScopeForbidden"
          },
          "429": {
            "$ref": "#/components/responses/v1_RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/exports/visits": {
      "get": {
        "operationId": "v1ExportVisits",
        "tags": [
          "Exports"
        ],
        "summary": "Export visits as CSV or JSON",
        "description": "Bulk-exports visit records for a date range, with the same date validation, per-request row cap and pagination as the other exports. Visits have no synthetic partition, so there is no `source` parameter.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "read:export"
            ]
          }
        ],
        "parameters": [
          {
            "name": "format",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "csv"
              ],
              "default": "json"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "domain_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The exported page, as a JSON envelope or a raw CSV body depending on `format`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "count",
                    "limit",
                    "truncated",
                    "from",
                    "to",
                    "visits"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "count": {
                      "type": "integer"
                    },
                    "limit": {
                      "type": "integer"
                    },
                    "truncated": {
                      "type": "boolean"
                    },
                    "from": {
                      "type": "string"
                    },
                    "to": {
                      "type": "string"
                    },
                    "next_cursor": {
                      "type": "string"
                    },
                    "visits": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "device_id": {
                            "type": "string"
                          },
                          "domain_id": {
                            "type": "string"
                          },
                          "country": {
                            "type": "string"
                          },
                          "city": {
                            "type": "string"
                          },
                          "external_user_id": {
                            "type": "string"
                          },
                          "created_at": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "count": 1,
                  "limit": 1,
                  "truncated": true,
                  "from": "example-from",
                  "to": "example-to",
                  "next_cursor": "cursor_000123",
                  "visits": [
                    {
                      "id": "example-id",
                      "device_id": "dev_7a2b9c4d1e6f3a8b5c2d9e4f7a1b6c3d",
                      "domain_id": "dom_3f2a8c91d6e5f470",
                      "country": "US",
                      "city": "Istanbul",
                      "external_user_id": "example-external_user_id",
                      "created_at": "2026-09-13T12:00:00.000Z"
                    }
                  ]
                }
              },
              "text/csv": {
                "schema": {
                  "type": "string"
                },
                "example": "example-v1ExportVisits"
              }
            },
            "headers": {
              "X-Noxtica-Export-Truncated": {
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              },
              "X-Noxtica-Export-Next-Cursor": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "`Invalid format`, missing `from`/`to`, or invalid date shape/calendar.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/v1_InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/v1_ScopeForbidden"
          },
          "429": {
            "$ref": "#/components/responses/v1_RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/exports/scored-events": {
      "get": {
        "operationId": "v1ExportScoredEvents",
        "tags": [
          "Exports"
        ],
        "summary": "Stream scored events as JSON Lines",
        "description": "Streams scored events as newline-delimited JSON, newest first: one scored-event object per line, followed by a trailing `_summary` line. The stream is capped at a fixed maximum number of rows per request.\n\n- `tier` is coarser than `gpuAttestationTier` on `GET /v1/device/{deviceId}`: only a hardware-attested device maps to `attested`; everything else is `suspicious`.\n- `band` is one of `critical`, `high`, `medium`, `low`, `minimal`; an unrecognised stored value is reported as `minimal`.\n- `reason_codes` holds at most 64 entries and is empty unless reason-code output is enabled for your organisation.\n\nThis route validates the shape of `from` and `to` only, not calendar validity, unlike the JSON/CSV exports.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "read:export"
            ]
          }
        ],
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "REQUIRED. `YYYY-MM-DD`, `YYYY-MM-DD HH:MM:SS`, or ISO 8601."
          },
          {
            "name": "to",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "domain_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Opaque keyset cursor from a prior response's `next_cursor` (in the trailing `_summary` line). No cursor param on page 1."
          }
        ],
        "responses": {
          "200": {
            "description": "JSONL body: one scored-event object per line, then a trailing `_summary` line.",
            "content": {
              "application/x-ndjson": {
                "schema": {
                  "type": "string",
                  "description": "Newline-delimited JSON. Each event line: `{id, device_id, domain_id, score, tier, band, confidence, reason_codes, created_at}`. The final line is always `{_summary: true, count, from, to, explainabilityEnabled, limit, truncated, next_cursor?}`."
                },
                "example": "example-v1ExportScoredEvents"
              }
            },
            "headers": {
              "X-Noxtica-Export-Truncated": {
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              },
              "X-Noxtica-Export-Next-Cursor": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Missing `from`/`to`, or a value not matching the accepted date shape (this route validates SHAPE only, not calendar validity, unlike the sibling JSON/CSV exports).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/v1_InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/v1_ScopeForbidden"
          },
          "429": {
            "$ref": "#/components/responses/v1_RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/emerging-threats": {
      "get": {
        "operationId": "v1GetEmergingThreats",
        "tags": [
          "Exports"
        ],
        "summary": "Read reason-code firing counts",
        "description": "Returns per-reason-code firing counts and rates over a bounded lookback window, aggregated from the published reason-code catalogue. It reuses the `read:export` scope.\n\nThe report is disabled unless it is enabled for the deployment. When it is, the route does no warehouse work and answers a neutral `200` with `{\"available\":false,\"reason\":\"feature_unavailable\",\"signals\":[]}`, so you can always probe it safely. A warehouse read fault degrades to an empty `signals` array and `window_sessions: 0`; this route never answers `500` for it.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "read:export"
            ]
          }
        ],
        "parameters": [
          {
            "name": "window",
            "in": "query",
            "schema": {
              "type": "integer",
              "enum": [
                1,
                6,
                24,
                168,
                720
              ],
              "default": 24
            },
            "description": "Lookback hours; any other value silently falls back to 24."
          }
        ],
        "responses": {
          "200": {
            "description": "The firing-count report, or the feature-disabled neutral empty state.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "available",
                    "window_hours",
                    "signals",
                    "count"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "available": {
                      "type": "boolean"
                    },
                    "reason": {
                      "type": "string",
                      "enum": [
                        "feature_unavailable"
                      ]
                    },
                    "window_hours": {
                      "type": "integer"
                    },
                    "window_sessions": {
                      "type": "integer",
                      "description": "Present only when available is true."
                    },
                    "signals": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "reason_code": {
                            "type": "string"
                          },
                          "domain": {
                            "type": "string"
                          },
                          "label": {
                            "type": "string"
                          },
                          "firing_count": {
                            "type": "integer"
                          },
                          "firing_rate": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "`null` when `window_sessions` is below the 20-session display floor."
                          }
                        }
                      }
                    },
                    "count": {
                      "type": "integer"
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "available": true,
                  "reason": "feature_unavailable",
                  "window_hours": 1,
                  "window_sessions": 1,
                  "signals": [
                    {
                      "reason_code": "example-reason_code",
                      "domain": "app.example.com",
                      "label": "example-label",
                      "firing_count": 1,
                      "firing_rate": 1
                    }
                  ],
                  "count": 1
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/v1_InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/v1_ScopeForbidden"
          },
          "429": {
            "$ref": "#/components/responses/v1_RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/sealed-results/key": {
      "get": {
        "operationId": "v1GetSealedResultsKey",
        "tags": [
          "Sealed Results"
        ],
        "summary": "Fetch the key that opens Sealed Client Results",
        "description": "Returns your organisation's symmetric key for opening Sealed Client Results envelopes. The key is derived on demand and never stored.\n\n`keyVersion` is optional. Each sealed envelope carries the cleartext `kv` (key version) it was sealed under, and this route serves any past version that has not been revoked, so rotation never orphans an archived envelope. `expiresAt` is present only when a key lifetime is configured.\n\n- `404 sealed_key_version_unavailable` — `keyVersion` is not a positive integer or is newer than the current version. No key material is returned.\n- `403` — the key lacks `read:sealed_results`, or the key is revoked for this organisation and version.\n- `500 server_misconfigured` — sealed results are not provisioned for this deployment; this is distinct from an authentication failure.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "read:sealed_results"
            ]
          }
        ],
        "parameters": [
          {
            "name": "keyVersion",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^[1-9][0-9]{0,8}$"
            },
            "description": "Key version to fetch — the `kv` a Sealed Client Result envelope carries. Omitted = the current version (the response is unchanged). A past version is served from the server's master ring until it is REVOKED for the tenant (`403`, as for the current version). A malformed or future version answers `404 sealed_key_version_unavailable`."
          }
        ],
        "responses": {
          "200": {
            "description": "The tenant's sealed-results key material.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "keyVersion",
                    "key",
                    "alg",
                    "envelope"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "keyVersion": {
                      "type": "string"
                    },
                    "key": {
                      "type": "string",
                      "description": "base64-encoded raw derived key."
                    },
                    "alg": {
                      "type": "string"
                    },
                    "envelope": {
                      "type": "string",
                      "enum": [
                        "noxtica-sealed-v1"
                      ]
                    },
                    "expiresAt": {
                      "type": "integer",
                      "description": "Absolute epoch-ms expiry hint; present only when a TTL is configured."
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "keyVersion": "example-keyVersion",
                  "key": "example-key",
                  "alg": "example-alg",
                  "envelope": "noxtica-sealed-v1",
                  "expiresAt": 1768435200
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/v1_InvalidApiKey"
          },
          "403": {
            "description": "`API key does not have read:sealed_results scope`, OR the sealed-results key is revoked for this tenant/version (`sealed-results key revoked for this tenant/version`).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    },
                    "requestId": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "404": {
            "description": "`sealed_key_version_unavailable` — the requested `keyVersion` is not a positive integer, or is newer than the current key version. Explicit (never a 500); no key material is returned.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "error",
                    "code"
                  ],
                  "properties": {
                    "error": {
                      "type": "string"
                    },
                    "code": {
                      "type": "string",
                      "enum": [
                        "sealed_key_version_unavailable"
                      ]
                    },
                    "requestId": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "error": "sealed-results key version unavailable",
                  "code": "sealed_key_version_unavailable",
                  "requestId": "req-test"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/v1_RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/labels": {
      "get": {
        "operationId": "v1ListLabels",
        "tags": [
          "Labels"
        ],
        "summary": "List your organisation's ground-truth labels",
        "description": "Lists the labels your organisation has written with `POST /v1/labels`, with optional `device_id` and `label` filters and a keyset cursor over `(created_at, id)` (the same opaque cursor shape as `GET /v1/events`). It reuses the `read:device` scope; there is no separate read-labels scope.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "read:device"
            ]
          }
        ],
        "parameters": [
          {
            "name": "device_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "label",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "bot",
                "human",
                "fraud",
                "legit",
                "unknown"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 200
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of labels.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "labels",
                    "hasMore",
                    "nextCursor"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "labels": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "deviceId": {
                            "type": "string"
                          },
                          "eventId": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "label": {
                            "type": "string",
                            "enum": [
                              "bot",
                              "human",
                              "fraud",
                              "legit",
                              "unknown"
                            ]
                          },
                          "source": {
                            "type": "string"
                          },
                          "note": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "updatedAt": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    },
                    "hasMore": {
                      "type": "boolean"
                    },
                    "nextCursor": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "labels": [
                    {
                      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                      "deviceId": "dev_7a2b9c4d1e6f3a8b5c2d9e4f7a1b6c3d",
                      "eventId": "evt_3c9b2f7e4a3d4c8e9f1a2b3c4d5e6f70",
                      "label": "bot",
                      "source": "example-source",
                      "note": "created via API",
                      "createdAt": "2026-09-13T12:00:00.000Z",
                      "updatedAt": "2026-09-13T12:00:00.000Z"
                    }
                  ],
                  "hasMore": true,
                  "nextCursor": "cursor_000123"
                }
              }
            }
          },
          "400": {
            "description": "`Invalid label. Expected one of: bot, human, fraud, legit, unknown`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/v1_InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/v1_ScopeForbidden"
          },
          "429": {
            "$ref": "#/components/responses/v1_RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "x-noxtica-status": "available"
      },
      "post": {
        "operationId": "v1WriteLabel",
        "tags": [
          "Labels"
        ],
        "summary": "Write a ground-truth label for a device",
        "description": "Records a confirmed fraud, legitimate or other label for a device, optionally scoped to one event, to calibrate scoring. The write is an upsert: repeating the same `(device_id, event_id)` updates `label`, `source`, `note` and `updated_at` on the existing row instead of creating a duplicate.\n\nThe body accepts only `device_id`, `label`, `event_id`, `note` and `source`; any other key is rejected with `400 Unknown field`. `label` must be one of `bot`, `human`, `fraud`, `legit`, `unknown`.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "write:labels"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "device_id",
                  "label"
                ],
                "additionalProperties": false,
                "properties": {
                  "device_id": {
                    "type": "string",
                    "maxLength": 256
                  },
                  "label": {
                    "type": "string",
                    "enum": [
                      "bot",
                      "human",
                      "fraud",
                      "legit",
                      "unknown"
                    ]
                  },
                  "event_id": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 256,
                    "description": "Optional; blank/whitespace-only normalizes to NULL (collapses onto the device-level idempotency slot)."
                  },
                  "note": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 1024
                  },
                  "source": {
                    "type": "string",
                    "maxLength": 64,
                    "default": "api",
                    "description": "Truncated to 64 chars; defaults to 'api' when omitted/blank."
                  }
                }
              },
              "example": {
                "device_id": "dev_7a2b9c4d1e6f3a8b5c2d9e4f7a1b6c3d",
                "label": "bot",
                "event_id": "evt_3c9b2f7e4a3d4c8e9f1a2b3c4d5e6f70",
                "note": "created via API",
                "source": "api"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The upserted (inserted or updated) label row.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "label"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "label": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "deviceId": {
                          "type": "string"
                        },
                        "eventId": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "label": {
                          "type": "string",
                          "enum": [
                            "bot",
                            "human",
                            "fraud",
                            "legit",
                            "unknown"
                          ]
                        },
                        "source": {
                          "type": "string"
                        },
                        "note": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "createdAt": {
                          "type": "string",
                          "format": "date-time"
                        },
                        "updatedAt": {
                          "type": "string",
                          "format": "date-time"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "label": {
                    "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                    "deviceId": "dev_7a2b9c4d1e6f3a8b5c2d9e4f7a1b6c3d",
                    "eventId": "evt_3c9b2f7e4a3d4c8e9f1a2b3c4d5e6f70",
                    "label": "bot",
                    "source": "example-source",
                    "note": "created via API",
                    "createdAt": "2026-09-13T12:00:00.000Z",
                    "updatedAt": "2026-09-13T12:00:00.000Z"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Unknown body field, missing/oversized `device_id`, invalid `label`, or an oversized `event_id`/`note`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/v1_InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/v1_ScopeForbidden"
          },
          "413": {
            "$ref": "#/components/responses/v1_BodyTooLarge"
          },
          "415": {
            "description": "`Content-Type must be application/json`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/v1_RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/generator/fingerprints": {
      "post": {
        "operationId": "v1GenerateFingerprintBatch",
        "tags": [
          "Generator"
        ],
        "summary": "Generate a batch of synthetic devices",
        "description": "Generates `count` synthetic devices, each with `eventsPerDevice` events, derived deterministically from real template fingerprints, for testing and load. Read them back with `source=synthetic`.\n\nThe call is idempotent on `(domain_id, seed)`: a repeated identical request returns the same existing batch with `isExisting: true` and HTTP `200`; a new batch answers `201`. `domain_id` must be an active domain of your organisation, otherwise the route answers `404`.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "write:generate"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "domain_id",
                  "seed"
                ],
                "properties": {
                  "domain_id": {
                    "type": "string"
                  },
                  "seed": {
                    "type": "string",
                    "description": "Idempotency key for the whole batch."
                  },
                  "count": {
                    "type": "integer",
                    "default": 10,
                    "minimum": 1,
                    "maximum": 100,
                    "description": "Coerced via Number(); non-positive/non-finite falls back to 10."
                  },
                  "eventsPerDevice": {
                    "type": "integer",
                    "default": 3,
                    "minimum": 1,
                    "maximum": 10
                  },
                  "sourceFrom": {
                    "type": "string"
                  },
                  "sourceTo": {
                    "type": "string"
                  },
                  "sourceLimit": {
                    "type": "integer",
                    "default": 200,
                    "maximum": 500
                  },
                  "scrubIPs": {
                    "type": "boolean",
                    "default": true,
                    "description": "Any value other than the literal `false` is treated as true."
                  }
                }
              },
              "example": {
                "domain_id": "dom_3f2a8c91d6e5f470",
                "seed": "seed-01",
                "count": 10,
                "eventsPerDevice": 3,
                "sourceFrom": "example-sourceFrom",
                "sourceTo": "example-sourceTo",
                "sourceLimit": 200,
                "scrubIPs": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The existing batch, when `seed` already matches a committed batch for this `(tenant, domain)`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "isExisting",
                    "batchId",
                    "seed",
                    "tenantId",
                    "domainId",
                    "deviceIds",
                    "totalDevices",
                    "totalEvents",
                    "createdAt"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "isExisting": {
                      "type": "boolean"
                    },
                    "batchId": {
                      "type": "string"
                    },
                    "seed": {
                      "type": "string"
                    },
                    "tenantId": {
                      "type": "string"
                    },
                    "domainId": {
                      "type": "string"
                    },
                    "deviceIds": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "totalDevices": {
                      "type": "integer"
                    },
                    "totalEvents": {
                      "type": "integer"
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "isExisting": true,
                  "batchId": "batch_5a1f9c3e7b2d4a6f8091c2d3e4f5a6b7",
                  "seed": "seed-01",
                  "tenantId": "tenant_42",
                  "domainId": "dom_3f2a8c91d6e5f470",
                  "deviceIds": [
                    "example-deviceIds"
                  ],
                  "totalDevices": 1,
                  "totalEvents": 1,
                  "createdAt": "2026-09-13T12:00:00.000Z"
                }
              }
            }
          },
          "201": {
            "description": "A newly-committed batch.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "isExisting",
                    "batchId",
                    "seed",
                    "tenantId",
                    "domainId",
                    "deviceIds",
                    "totalDevices",
                    "totalEvents",
                    "createdAt"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "isExisting": {
                      "type": "boolean"
                    },
                    "batchId": {
                      "type": "string"
                    },
                    "seed": {
                      "type": "string"
                    },
                    "tenantId": {
                      "type": "string"
                    },
                    "domainId": {
                      "type": "string"
                    },
                    "deviceIds": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "totalDevices": {
                      "type": "integer"
                    },
                    "totalEvents": {
                      "type": "integer"
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "isExisting": true,
                  "batchId": "batch_5a1f9c3e7b2d4a6f8091c2d3e4f5a6b7",
                  "seed": "seed-01",
                  "tenantId": "tenant_42",
                  "domainId": "dom_3f2a8c91d6e5f470",
                  "deviceIds": [
                    "example-deviceIds"
                  ],
                  "totalDevices": 1,
                  "totalEvents": 1,
                  "createdAt": "2026-09-13T12:00:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`domain_id and seed are required`, or `No template fingerprints found in the specified range`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/v1_InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/v1_ScopeForbidden"
          },
          "404": {
            "description": "`Domain not found or does not belong to tenant`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "413": {
            "$ref": "#/components/responses/v1_BodyTooLarge"
          },
          "415": {
            "description": "`Content-Type must be application/json`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/generator/fingerprint": {
      "post": {
        "operationId": "v1GenerateSingleFingerprint",
        "tags": [
          "Generator"
        ],
        "summary": "Generate one seeded synthetic device",
        "description": "Generates one synthetic device from a filtered selection of real template fingerprints. It is idempotent on the derived seed key: a repeated request returns the existing device unchanged with `isExisting: true` and HTTP `200`; a new device answers `201`.\n\n`json_filters`, when present, constrain the candidate templates by JSONPath-style equality against the stored fingerprint, score and collector fields. Domain ownership, scope and body rules are the same as for `POST /v1/generator/fingerprints`.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "write:generate"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "domain_id",
                  "seed"
                ],
                "properties": {
                  "domain_id": {
                    "type": "string"
                  },
                  "seed": {
                    "type": "string"
                  },
                  "platform": {
                    "type": "string"
                  },
                  "risk_level": {
                    "type": "string"
                  },
                  "country": {
                    "type": "string"
                  },
                  "language": {
                    "type": "string"
                  },
                  "timezone": {
                    "type": "string"
                  },
                  "score_min": {
                    "type": "number"
                  },
                  "score_max": {
                    "type": "number"
                  },
                  "json_filters": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "required": [
                        "source",
                        "path"
                      ],
                      "properties": {
                        "source": {
                          "type": "string",
                          "enum": [
                            "fingerprint",
                            "score",
                            "cf"
                          ]
                        },
                        "path": {
                          "type": "string",
                          "description": "A JSONPath-style equality filter, e.g. $.signals.webgl.vendor."
                        },
                        "value": {}
                      }
                    },
                    "description": "Normalized/hashed into the deterministic seed key alongside `seed`."
                  },
                  "sourceFrom": {
                    "type": "string"
                  },
                  "sourceTo": {
                    "type": "string"
                  },
                  "sourceLimit": {
                    "type": "integer",
                    "default": 200,
                    "maximum": 500
                  },
                  "scrubIPs": {
                    "type": "boolean",
                    "default": true
                  }
                }
              },
              "example": {
                "domain_id": "dom_3f2a8c91d6e5f470",
                "seed": "seed-01",
                "platform": "example-platform",
                "risk_level": "low",
                "country": "US",
                "language": "example-language",
                "timezone": "example-timezone",
                "score_min": 1,
                "score_max": 1,
                "json_filters": [
                  {
                    "source": "fingerprint",
                    "path": "/v1/kyc/verify",
                    "value": "example-value"
                  }
                ],
                "sourceFrom": "example-sourceFrom",
                "sourceTo": "example-sourceTo",
                "sourceLimit": 200,
                "scrubIPs": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The existing seeded fingerprint (returned unchanged, `Cache-Control: no-store`).",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "enum": [
                    "no-store"
                  ]
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "isExisting",
                    "seed",
                    "filters",
                    "tenantId",
                    "domainId",
                    "batchId",
                    "deviceId",
                    "templateEventId",
                    "fingerprint",
                    "score",
                    "cf",
                    "createdAt",
                    "updatedAt"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "isExisting": {
                      "type": "boolean"
                    },
                    "seed": {
                      "type": "string"
                    },
                    "filters": {
                      "type": "object",
                      "additionalProperties": true,
                      "description": "The normalized template filters echoed back."
                    },
                    "tenantId": {
                      "type": "string"
                    },
                    "domainId": {
                      "type": "string"
                    },
                    "batchId": {
                      "type": "string"
                    },
                    "deviceId": {
                      "type": "string"
                    },
                    "templateEventId": {
                      "type": "string"
                    },
                    "fingerprint": {
                      "type": "object",
                      "additionalProperties": true,
                      "description": "The stored synthetic fingerprint blob (template-derived; shape not locally schema-validated)."
                    },
                    "score": {
                      "type": "object",
                      "additionalProperties": true,
                      "description": "The stored score blob copied verbatim from the selected template."
                    },
                    "cf": {
                      "type": "object",
                      "additionalProperties": true,
                      "description": "The stored Cloudflare-geo blob, IP-scrubbed when scrubIPs is true."
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "isExisting": true,
                  "seed": "seed-01",
                  "filters": {},
                  "tenantId": "tenant_42",
                  "domainId": "dom_3f2a8c91d6e5f470",
                  "batchId": "batch_5a1f9c3e7b2d4a6f8091c2d3e4f5a6b7",
                  "deviceId": "dev_7a2b9c4d1e6f3a8b5c2d9e4f7a1b6c3d",
                  "templateEventId": "example-templateEventId",
                  "fingerprint": {},
                  "score": {},
                  "cf": {},
                  "createdAt": "2026-09-13T12:00:00.000Z",
                  "updatedAt": "2026-09-13T12:00:00.000Z"
                }
              }
            }
          },
          "201": {
            "description": "A newly-committed seeded fingerprint.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "enum": [
                    "no-store"
                  ]
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "isExisting",
                    "seed",
                    "filters",
                    "tenantId",
                    "domainId",
                    "batchId",
                    "deviceId",
                    "templateEventId",
                    "fingerprint",
                    "score",
                    "cf",
                    "createdAt",
                    "updatedAt"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "isExisting": {
                      "type": "boolean"
                    },
                    "seed": {
                      "type": "string"
                    },
                    "filters": {
                      "type": "object",
                      "additionalProperties": true,
                      "description": "The normalized template filters echoed back."
                    },
                    "tenantId": {
                      "type": "string"
                    },
                    "domainId": {
                      "type": "string"
                    },
                    "batchId": {
                      "type": "string"
                    },
                    "deviceId": {
                      "type": "string"
                    },
                    "templateEventId": {
                      "type": "string"
                    },
                    "fingerprint": {
                      "type": "object",
                      "additionalProperties": true,
                      "description": "The stored synthetic fingerprint blob (template-derived; shape not locally schema-validated)."
                    },
                    "score": {
                      "type": "object",
                      "additionalProperties": true,
                      "description": "The stored score blob copied verbatim from the selected template."
                    },
                    "cf": {
                      "type": "object",
                      "additionalProperties": true,
                      "description": "The stored Cloudflare-geo blob, IP-scrubbed when scrubIPs is true."
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "updatedAt": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "isExisting": true,
                  "seed": "seed-01",
                  "filters": {},
                  "tenantId": "tenant_42",
                  "domainId": "dom_3f2a8c91d6e5f470",
                  "batchId": "batch_5a1f9c3e7b2d4a6f8091c2d3e4f5a6b7",
                  "deviceId": "dev_7a2b9c4d1e6f3a8b5c2d9e4f7a1b6c3d",
                  "templateEventId": "example-templateEventId",
                  "fingerprint": {},
                  "score": {},
                  "cf": {},
                  "createdAt": "2026-09-13T12:00:00.000Z",
                  "updatedAt": "2026-09-13T12:00:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`domain_id and seed are required`, or `No template fingerprints found matching the specified filters`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/v1_InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/v1_ScopeForbidden"
          },
          "404": {
            "description": "`Domain not found or does not belong to tenant`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "413": {
            "$ref": "#/components/responses/v1_BodyTooLarge"
          },
          "415": {
            "description": "`Content-Type must be application/json`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/verify/reputation": {
      "post": {
        "operationId": "v1VerifyReputation",
        "tags": [
          "Reputation"
        ],
        "summary": "Check email, website and phone reputation",
        "description": "Evaluates the reputation of an email address, a website and/or a phone number supplied by your backend and returns a fused verdict. At least one of `email`, `website` or `phone` is required. The checks are bounded and fail open: a check that cannot complete contributes no signal instead of failing the call.\n\nThis operation is not enabled by default. When the reputation module is not enabled for your organisation the route answers the `GatedNotFound` 404, and it does so before the API key is checked. A served call counts toward your organisation's reputation usage. Raw email and website values are not logged.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "read:reputation"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "At least one of `email`, `website`, `phone` is required.",
                "properties": {
                  "email": {
                    "type": "string"
                  },
                  "website": {
                    "type": "string"
                  },
                  "phone": {
                    "type": "string"
                  }
                }
              },
              "example": {
                "email": "example-email",
                "website": "example-website",
                "phone": "example-phone"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The fused reputation verdict.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "verdict",
                    "signals",
                    "confidence"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "verdict": {
                      "type": "string"
                    },
                    "signals": {
                      "type": "object",
                      "additionalProperties": true,
                      "description": "Per-signal sub-scores from `evaluateReputation`; the engine's internal signal-shape union is not locally re-validated by this handler."
                    },
                    "confidence": {
                      "type": "number"
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "verdict": "example-verdict",
                  "signals": {},
                  "confidence": 1
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/v1_InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/v1_InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/v1_ScopeForbidden"
          },
          "404": {
            "$ref": "#/components/responses/v1_GatedNotFound"
          },
          "429": {
            "$ref": "#/components/responses/v1_RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/crawl/vouchers": {
      "post": {
        "operationId": "v1MintCrawlVoucher",
        "tags": [
          "Crawl Vouchers"
        ],
        "summary": "Mint a crawler-access voucher",
        "description": "Mints a signed, stateless voucher that a verified crawler (identified by `agentKey`) presents to your Noxtica edge to satisfy a `charge` pricing rule. The edge verifies only the signature and binding. The response's `header` field names the request header that carries the voucher.\n\nThe voucher is always scoped to the organisation that owns the API key; a tenant id in the body is never used. The route is fail-closed: it answers `503` when no signing key is available and never emits an unsigned voucher.\n\nPayment capture is not part of this operation. It does not verify that a payment was taken; it only checks that a payment reference (`paymentRef` in the body, or the payment-reference request header) is present, and only requires one when your deployment is configured to. Outstanding vouchers are capped per month, and the cap is claimed only after the voucher has been signed, so a signing failure never consumes it.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "write:crawl_voucher"
            ]
          }
        ],
        "parameters": [
          {
            "name": "X-Nox-Payment-Ref",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Alternative to the body's `paymentRef`; operator-attested, not independently verified this iteration."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "agentKey"
                ],
                "properties": {
                  "agentKey": {
                    "type": "string",
                    "maxLength": 256,
                    "description": "The crawler identity this voucher pays for ('*' = the catch-all pricing rule)."
                  },
                  "ttlSeconds": {
                    "type": "integer",
                    "default": 3600,
                    "minimum": 60,
                    "maximum": 86400
                  },
                  "paymentRef": {
                    "type": "string",
                    "description": "Operator-attested payment reference; presence-only checked."
                  }
                }
              },
              "example": {
                "agentKey": "example-agentKey",
                "ttlSeconds": 3600,
                "paymentRef": "example-paymentRef"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The minted voucher.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "voucher",
                    "expiresAt",
                    "header"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "voucher": {
                      "type": "string",
                      "description": "`<base64url(payload)>.<base64url(hmac)>`, or the HMAC-signing-trust envelope form when that feature is armed."
                    },
                    "expiresAt": {
                      "type": "integer",
                      "description": "Epoch seconds."
                    },
                    "header": {
                      "type": "string",
                      "enum": [
                        "X-Nox-Crawl-Voucher"
                      ]
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "voucher": "example-voucher",
                  "expiresAt": 1768435200,
                  "header": "X-Nox-Crawl-Voucher"
                }
              }
            }
          },
          "400": {
            "description": "`agentKey (non-empty string) is required`, or `Invalid JSON body`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/v1_InvalidApiKey"
          },
          "402": {
            "description": "`Payment context required` — returned only when the deployment requires a payment reference and neither `paymentRef` nor the payment-reference header was supplied.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/v1_ScopeForbidden"
          },
          "413": {
            "$ref": "#/components/responses/v1_BodyTooLarge"
          },
          "415": {
            "description": "`Content-Type must be application/json`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/v1_RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "description": "`Crawl voucher minting is not configured` (no signing key is available) or `Voucher quota authority unavailable`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/behavioral/subjects/{subjectRef}": {
      "get": {
        "operationId": "v1GetBehavioralSubject",
        "tags": [
          "Behavioral Baseline"
        ],
        "summary": "Read a subject's behavioral baseline",
        "description": "Reads a subject's current behavioral-baseline enrollment and its latest drift snapshot. `subjectRef` is your raw end-user account id: it is never stored, logged or echoed, only keyed-hashed server-side before any lookup.\n\nNot enabled by default: the whole `/v1/behavioral/*` family answers the `GatedNotFound` 404 unless behavioral baselines are enabled for the deployment, and only then is the `read:behavioral` scope checked.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "read:behavioral"
            ]
          }
        ],
        "parameters": [
          {
            "name": "subjectRef",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 256
            },
            "description": "The tenant's raw end-user account id (hashed server-side; never stored as given)."
          }
        ],
        "responses": {
          "200": {
            "description": "The subject's baseline enrollment + latest drift.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "subject"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "subject": {
                      "type": "object",
                      "properties": {
                        "enrollmentStatus": {
                          "type": "string",
                          "enum": [
                            "learning",
                            "active"
                          ],
                          "description": "A persisted value outside the closed set clamps to `learning`."
                        },
                        "sampleCount": {
                          "type": "integer"
                        },
                        "attestationProvenance": {
                          "type": "object",
                          "properties": {
                            "gpu_attested": {
                              "type": "integer"
                            },
                            "sealed": {
                              "type": "integer"
                            },
                            "unattested": {
                              "type": "integer"
                            }
                          }
                        },
                        "deviation": {
                          "type": [
                            "number",
                            "null"
                          ]
                        },
                        "families": {
                          "type": [
                            "object",
                            "null"
                          ],
                          "properties": {
                            "pointer": {
                              "type": [
                                "number",
                                "null"
                              ]
                            },
                            "keystroke": {
                              "type": [
                                "number",
                                "null"
                              ]
                            },
                            "cadence": {
                              "type": [
                                "number",
                                "null"
                              ]
                            }
                          }
                        },
                        "lastDriftAt": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "format": "date-time"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "subject": {
                    "enrollmentStatus": "learning",
                    "sampleCount": 1,
                    "attestationProvenance": {
                      "gpu_attested": 1,
                      "sealed": 1,
                      "unattested": 1
                    },
                    "deviation": 1,
                    "families": {
                      "pointer": 1,
                      "keystroke": 1,
                      "cadence": 1
                    },
                    "lastDriftAt": "2026-09-13T12:00:00.000Z"
                  }
                }
              }
            }
          },
          "400": {
            "description": "`Invalid subjectRef` — empty or over 256 chars.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/v1_InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/v1_ScopeForbidden"
          },
          "404": {
            "description": "`Subject not found` (no current snapshot exists), or `V1 endpoint not found` when behavioral baselines are not enabled for the deployment.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/v1_RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "x-noxtica-status": "available"
      },
      "delete": {
        "operationId": "v1EraseBehavioralSubject",
        "tags": [
          "Behavioral Baseline"
        ],
        "summary": "Erase a subject's behavioral baseline",
        "description": "Erases a subject's behavioral baseline, for data-subject erasure requests. Live profile state is erased first, then the stored snapshots and drift projections are hard-deleted. If the live-state erase fails the route answers `502` with `{\"ok\":false,\"profileErased\":false,...}` instead of a false `200`, because a surviving profile could otherwise re-flush the erased snapshot; the call is safe to retry. Erasing an unknown or already-erased subject is idempotent and answers `200 {\"deleted\":{\"snapshots\":0,\"driftEvents\":0}}`.\n\nThis erases account-scoped (`acct:`) subjects only. Device-scoped baselines and the raw behavioral tracks need the separate per-device erasure path in the Backoffice, so a subject with both needs both paths. Availability is the same as for `GET /v1/behavioral/subjects/{subjectRef}`.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "erase:behavioral"
            ]
          }
        ],
        "parameters": [
          {
            "name": "subjectRef",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 256
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Erasure completed (or was already a no-op for an unknown subject).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "profileErased",
                    "deleted"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "profileErased": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "deleted": {
                      "type": "object",
                      "properties": {
                        "snapshots": {
                          "type": "integer"
                        },
                        "driftEvents": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "profileErased": true,
                  "deleted": {
                    "snapshots": 1,
                    "driftEvents": 1
                  }
                }
              }
            }
          },
          "400": {
            "description": "`Invalid subjectRef` — empty or over 256 chars.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/v1_InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/v1_ScopeForbidden"
          },
          "404": {
            "description": "`Subject not found`, or `V1 endpoint not found` when behavioral baselines are not enabled for the deployment.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/v1_RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "502": {
            "description": "`{ ok:false, profileErased:false, deleted, error: 'behavioral profile durable-object erase failed — retry (idempotent)' }` — the erase call is safe to retry.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "profileErased": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "deleted": {
                      "type": "object",
                      "properties": {
                        "snapshots": {
                          "type": "integer"
                        },
                        "driftEvents": {
                          "type": "integer"
                        }
                      }
                    },
                    "error": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "ok": false,
                  "profileErased": false,
                  "deleted": {
                    "snapshots": 1,
                    "driftEvents": 1
                  },
                  "error": "invalid_request"
                }
              }
            }
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/behavioral/subjects/{subjectRef}/timeline": {
      "get": {
        "operationId": "v1GetBehavioralSubjectTimeline",
        "tags": [
          "Behavioral Baseline"
        ],
        "summary": "Read a subject's drift-event history",
        "description": "Reads a subject's drift events, newest first. The row cap is clamped to 1–100 and there is no pagination cursor on this route. `subjectRef` handling and availability are the same as for `GET /v1/behavioral/subjects/{subjectRef}`.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "read:behavioral"
            ]
          }
        ],
        "parameters": [
          {
            "name": "subjectRef",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 256
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The subject's drift-event timeline.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "events",
                    "count"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "events": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "deviation": {
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "families": {
                            "type": [
                              "object",
                              "null"
                            ],
                            "properties": {
                              "pointer": {
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "keystroke": {
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "cadence": {
                                "type": [
                                  "number",
                                  "null"
                                ]
                              }
                            }
                          },
                          "attestation": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "channel": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "createdAt": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    },
                    "count": {
                      "type": "integer"
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "events": [
                    {
                      "deviation": 1,
                      "families": {
                        "pointer": 1,
                        "keystroke": 1,
                        "cadence": 1
                      },
                      "attestation": "example-attestation",
                      "channel": "example-channel",
                      "createdAt": "2026-09-13T12:00:00.000Z"
                    }
                  ],
                  "count": 1
                }
              }
            }
          },
          "400": {
            "description": "`Invalid subjectRef` — empty or over 256 chars.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/v1_InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/v1_ScopeForbidden"
          },
          "404": {
            "description": "`Subject not found`, or `V1 endpoint not found` when behavioral baselines are not enabled for the deployment.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/v1_RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/agent/passport": {
      "get": {
        "operationId": "getAgentPassport",
        "tags": [
          "Agent Trust"
        ],
        "summary": "Issue a signed Agent Passport (GET)",
        "description": "Runs the same Web Bot Auth verdict as `POST /v1/agent/verify` (RFC 9421 signature verification plus your organisation's agent policy registry) and returns one ES256-signed, offline-verifiable envelope. Verify the signature against the published JWKS (`GET /.well-known/noxtica/agent-passport-jwks.json`, falling back to `/.well-known/noxtica/jwks.json`) by `kid`; no round trip to Noxtica is needed.\n\nThe GET form reads only the three Web Bot Auth headers of the incoming request (`signature-input`, `signature`, `signature-agent`) and an optional forwarded attestation from the query parameters `tier`, `anchored`, `riskBand` and `jti`. `sub` is set only for a cryptographically `verified` verdict; every other verdict carries `sub: null`. An unverified `allow` is withheld or downgraded before signing.\n\n**Availability.** Agent Passports are not enabled by default. When they are not enabled for the deployment the route answers `404 {\"error\":\"Not found\"}`, a different body from the usual `V1 endpoint not found`; when your organisation has not opted into agent verification it answers `403 {\"error\":\"feature disabled\"}`. The route shares its rate-limit bucket with `POST /v1/agent/verify`, and a verified issuance counts toward your agent-verification usage.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "read:device"
            ]
          }
        ],
        "parameters": [
          {
            "name": "url",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "The signed target URI `@authority` is reconstructed from; degrades to the request's own URL when absent/malformed."
          },
          {
            "name": "tier",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "hardware",
                "software",
                "suspicious",
                "unavailable",
                "failed"
              ]
            },
            "description": "Optional caller-forwarded attestation tier; a non-member value is silently dropped (fail-open)."
          },
          {
            "name": "anchored",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            },
            "description": "Optional caller-forwarded \"server-anchored single-use claim succeeded\" flag; only the literal string `true` is honoured."
          },
          {
            "name": "riskBand",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "critical",
                "high",
                "medium",
                "low",
                "minimal"
              ]
            }
          },
          {
            "name": "jti",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "OPTIONAL caller-forwarded device-correlation id, echoed back as the passport's untrusted `cid` (never the server-minted replay `jti`)."
          }
        ],
        "responses": {
          "200": {
            "description": "The ES256-signed Agent Passport envelope (`SignedEnvelope<AgentPassportPayload>`). A tenant backend verifies this OFFLINE against the published JWKS by `kid` — no round-trip to Noxtica is required.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "alg",
                    "kid",
                    "iat",
                    "payload",
                    "sig"
                  ],
                  "properties": {
                    "alg": {
                      "type": "string",
                      "enum": [
                        "ES256"
                      ]
                    },
                    "kid": {
                      "type": "string"
                    },
                    "iat": {
                      "type": "integer",
                      "description": "Epoch seconds."
                    },
                    "exp": {
                      "type": "integer",
                      "description": "Epoch seconds; the signed expiry window (== the payload `ttl`)."
                    },
                    "kv": {
                      "type": "integer",
                      "description": "OPTIONAL signing key-version; present only when the trust-lifecycle signer is in use."
                    },
                    "spv": {
                      "type": "integer",
                      "description": "OPTIONAL signing-policy-version; same presence contract as `kv`."
                    },
                    "sig": {
                      "type": "string",
                      "description": "base64url ES256 signature over the payload."
                    },
                    "payload": {
                      "type": "object",
                      "required": [
                        "typ",
                        "iss",
                        "aud",
                        "pv",
                        "verdict",
                        "attestation",
                        "riskBand",
                        "policyAction",
                        "jti",
                        "sub",
                        "tenantId",
                        "cid",
                        "disclosure",
                        "issuedAt",
                        "ttl"
                      ],
                      "properties": {
                        "typ": {
                          "type": "string",
                          "enum": [
                            "agent-passport"
                          ]
                        },
                        "iss": {
                          "type": "string",
                          "enum": [
                            "noxtica"
                          ]
                        },
                        "aud": {
                          "type": "string",
                          "description": "The authenticated tenant id (audience binding)."
                        },
                        "pv": {
                          "type": "integer",
                          "enum": [
                            1,
                            2
                          ],
                          "description": "Passport schema version: 1 = legacy claims, 2 = explicit `callerAsserted` trust marker (when enabled for the deployment)."
                        },
                        "verdict": {
                          "type": "string",
                          "enum": [
                            "verified",
                            "unsigned",
                            "invalid_signature",
                            "expired",
                            "replay"
                          ]
                        },
                        "attestation": {
                          "type": "object",
                          "properties": {
                            "tier": {
                              "type": "string",
                              "enum": [
                                "hardware",
                                "software",
                                "suspicious",
                                "unavailable",
                                "failed"
                              ]
                            },
                            "anchored": {
                              "type": "boolean"
                            },
                            "provenance": {
                              "type": "string",
                              "enum": [
                                "caller_attested"
                              ]
                            }
                          }
                        },
                        "callerAsserted": {
                          "type": "boolean",
                          "enum": [
                            true
                          ],
                          "description": "Present only when `pv:2`."
                        },
                        "riskBand": {
                          "type": "string",
                          "enum": [
                            "critical",
                            "high",
                            "medium",
                            "low",
                            "minimal"
                          ]
                        },
                        "policyAction": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "enum": [
                            "allow",
                            "deny"
                          ]
                        },
                        "graduatedAction": {
                          "type": "string",
                          "enum": [
                            "allow",
                            "observe",
                            "challenge",
                            "deny"
                          ],
                          "description": "Present only when graduated agent policy is enabled for your organisation."
                        },
                        "jti": {
                          "type": "string",
                          "format": "uuid",
                          "description": "SERVER-MINTED per-issuance id — the consumer MUST reject a repeated `jti` (replay)."
                        },
                        "sub": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "The verified subject (keyid, else the signature-agent host); null unless verdict is 'verified'."
                        },
                        "tenantId": {
                          "type": "string"
                        },
                        "cid": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "OPTIONAL untrusted caller-forwarded correlation id — never the replay id."
                        },
                        "disclosure": {
                          "type": [
                            "object",
                            "null"
                          ],
                          "properties": {
                            "required": {
                              "type": "boolean",
                              "enum": [
                                true
                              ]
                            },
                            "regulation": {
                              "type": "string",
                              "enum": [
                                "eu_ai_act_art_50"
                              ]
                            },
                            "obligation": {
                              "type": "string"
                            },
                            "agentVerified": {
                              "type": "boolean"
                            }
                          }
                        },
                        "issuedAt": {
                          "type": "string",
                          "format": "date-time"
                        },
                        "ttl": {
                          "type": "integer",
                          "description": "Seconds; the signed envelope `exp` window."
                        }
                      }
                    }
                  }
                },
                "example": {
                  "alg": "ES256",
                  "kid": "kid-2026-09",
                  "iat": 1,
                  "exp": 1,
                  "kv": 1,
                  "spv": 1,
                  "sig": "example-sig",
                  "payload": {
                    "typ": "agent-passport",
                    "iss": "noxtica",
                    "aud": "example-aud",
                    "pv": 1,
                    "verdict": "verified",
                    "attestation": {
                      "tier": "hardware",
                      "anchored": true,
                      "provenance": "caller_attested"
                    },
                    "callerAsserted": true,
                    "riskBand": "critical",
                    "policyAction": "allow",
                    "graduatedAction": "allow",
                    "jti": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                    "sub": "example-sub",
                    "tenantId": "tenant_42",
                    "cid": "example-cid",
                    "disclosure": {
                      "required": true,
                      "regulation": "eu_ai_act_art_50",
                      "obligation": "example-obligation",
                      "agentVerified": true
                    },
                    "issuedAt": "2026-09-13T12:00:00.000Z",
                    "ttl": 1
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/v1_InvalidApiKey"
          },
          "403": {
            "description": "Your organisation has not opted into agent verification (`feature disabled`).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "feature disabled"
                      ]
                    },
                    "requestId": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "error": "feature disabled",
                  "requestId": "req-test"
                }
              }
            }
          },
          "404": {
            "description": "Agent Passports are not enabled for this deployment. The body is `{\"error\":\"Not found\"}`, returned before the API key is checked.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "Not found"
                      ]
                    },
                    "requestId": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "error": "Not found",
                  "requestId": "req-test"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/v1_RateLimited"
          },
          "500": {
            "description": "Unexpected fault; the handler otherwise never throws.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "503": {
            "description": "The signing key is unavailable or invalid (fail-closed: there is no silent fallback to another key).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          }
        },
        "x-noxtica-status": "available"
      },
      "post": {
        "operationId": "postAgentPassport",
        "tags": [
          "Agent Trust"
        ],
        "summary": "Issue a signed Agent Passport (POST)",
        "description": "Same verdict and signing pipeline as `GET /v1/agent/passport`; the POST form lets your backend forward the signature material in the JSON body instead of request headers, like `POST /v1/agent/verify`. The same availability rules, error responses, rate-limit bucket and usage counting apply.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "read:device"
            ]
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "headers": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "string"
                    },
                    "description": "The forwarded Web Bot Auth signature headers (`signature-input`, `signature`, `signature-agent`, lower-cased keys); non-string values are dropped."
                  },
                  "url": {
                    "type": "string",
                    "format": "uri",
                    "description": "The signed target URI; a malformed value degrades to the request's own URL."
                  },
                  "method": {
                    "type": "string",
                    "description": "The signed HTTP method the signature covers; defaults to `GET` when omitted/blank."
                  },
                  "attestation": {
                    "type": "object",
                    "properties": {
                      "tier": {
                        "type": "string",
                        "enum": [
                          "hardware",
                          "software",
                          "suspicious",
                          "unavailable",
                          "failed"
                        ]
                      },
                      "anchored": {
                        "type": "boolean"
                      }
                    }
                  },
                  "riskBand": {
                    "type": "string",
                    "enum": [
                      "critical",
                      "high",
                      "medium",
                      "low",
                      "minimal"
                    ]
                  },
                  "jti": {
                    "type": "string",
                    "description": "OPTIONAL caller-forwarded device-correlation id, echoed back as the passport's untrusted `cid`."
                  }
                }
              },
              "example": {
                "headers": {
                  "key": "example-headers"
                },
                "url": "https://verify.noxtica.com/s/kycs.tenant_42.9f3a8b7c6d5e4f3a2b1c0d9e8f7a6b5c",
                "method": "example-method",
                "attestation": {
                  "tier": "hardware",
                  "anchored": true
                },
                "riskBand": "critical",
                "jti": "example-jti"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The ES256-signed Agent Passport envelope (`SignedEnvelope<AgentPassportPayload>`). A tenant backend verifies this OFFLINE against the published JWKS by `kid` — no round-trip to Noxtica is required.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "alg",
                    "kid",
                    "iat",
                    "payload",
                    "sig"
                  ],
                  "properties": {
                    "alg": {
                      "type": "string",
                      "enum": [
                        "ES256"
                      ]
                    },
                    "kid": {
                      "type": "string"
                    },
                    "iat": {
                      "type": "integer",
                      "description": "Epoch seconds."
                    },
                    "exp": {
                      "type": "integer",
                      "description": "Epoch seconds; the signed expiry window (== the payload `ttl`)."
                    },
                    "kv": {
                      "type": "integer",
                      "description": "OPTIONAL signing key-version; present only when the trust-lifecycle signer is in use."
                    },
                    "spv": {
                      "type": "integer",
                      "description": "OPTIONAL signing-policy-version; same presence contract as `kv`."
                    },
                    "sig": {
                      "type": "string",
                      "description": "base64url ES256 signature over the payload."
                    },
                    "payload": {
                      "type": "object",
                      "required": [
                        "typ",
                        "iss",
                        "aud",
                        "pv",
                        "verdict",
                        "attestation",
                        "riskBand",
                        "policyAction",
                        "jti",
                        "sub",
                        "tenantId",
                        "cid",
                        "disclosure",
                        "issuedAt",
                        "ttl"
                      ],
                      "properties": {
                        "typ": {
                          "type": "string",
                          "enum": [
                            "agent-passport"
                          ]
                        },
                        "iss": {
                          "type": "string",
                          "enum": [
                            "noxtica"
                          ]
                        },
                        "aud": {
                          "type": "string",
                          "description": "The authenticated tenant id (audience binding)."
                        },
                        "pv": {
                          "type": "integer",
                          "enum": [
                            1,
                            2
                          ],
                          "description": "Passport schema version: 1 = legacy claims, 2 = explicit `callerAsserted` trust marker (when enabled for the deployment)."
                        },
                        "verdict": {
                          "type": "string",
                          "enum": [
                            "verified",
                            "unsigned",
                            "invalid_signature",
                            "expired",
                            "replay"
                          ]
                        },
                        "attestation": {
                          "type": "object",
                          "properties": {
                            "tier": {
                              "type": "string",
                              "enum": [
                                "hardware",
                                "software",
                                "suspicious",
                                "unavailable",
                                "failed"
                              ]
                            },
                            "anchored": {
                              "type": "boolean"
                            },
                            "provenance": {
                              "type": "string",
                              "enum": [
                                "caller_attested"
                              ]
                            }
                          }
                        },
                        "callerAsserted": {
                          "type": "boolean",
                          "enum": [
                            true
                          ],
                          "description": "Present only when `pv:2`."
                        },
                        "riskBand": {
                          "type": "string",
                          "enum": [
                            "critical",
                            "high",
                            "medium",
                            "low",
                            "minimal"
                          ]
                        },
                        "policyAction": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "enum": [
                            "allow",
                            "deny"
                          ]
                        },
                        "graduatedAction": {
                          "type": "string",
                          "enum": [
                            "allow",
                            "observe",
                            "challenge",
                            "deny"
                          ],
                          "description": "Present only when graduated agent policy is enabled for your organisation."
                        },
                        "jti": {
                          "type": "string",
                          "format": "uuid",
                          "description": "SERVER-MINTED per-issuance id — the consumer MUST reject a repeated `jti` (replay)."
                        },
                        "sub": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "The verified subject (keyid, else the signature-agent host); null unless verdict is 'verified'."
                        },
                        "tenantId": {
                          "type": "string"
                        },
                        "cid": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "OPTIONAL untrusted caller-forwarded correlation id — never the replay id."
                        },
                        "disclosure": {
                          "type": [
                            "object",
                            "null"
                          ],
                          "properties": {
                            "required": {
                              "type": "boolean",
                              "enum": [
                                true
                              ]
                            },
                            "regulation": {
                              "type": "string",
                              "enum": [
                                "eu_ai_act_art_50"
                              ]
                            },
                            "obligation": {
                              "type": "string"
                            },
                            "agentVerified": {
                              "type": "boolean"
                            }
                          }
                        },
                        "issuedAt": {
                          "type": "string",
                          "format": "date-time"
                        },
                        "ttl": {
                          "type": "integer",
                          "description": "Seconds; the signed envelope `exp` window."
                        }
                      }
                    }
                  }
                },
                "example": {
                  "alg": "ES256",
                  "kid": "kid-2026-09",
                  "iat": 1,
                  "exp": 1,
                  "kv": 1,
                  "spv": 1,
                  "sig": "example-sig",
                  "payload": {
                    "typ": "agent-passport",
                    "iss": "noxtica",
                    "aud": "example-aud",
                    "pv": 1,
                    "verdict": "verified",
                    "attestation": {
                      "tier": "hardware",
                      "anchored": true,
                      "provenance": "caller_attested"
                    },
                    "callerAsserted": true,
                    "riskBand": "critical",
                    "policyAction": "allow",
                    "graduatedAction": "allow",
                    "jti": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                    "sub": "example-sub",
                    "tenantId": "tenant_42",
                    "cid": "example-cid",
                    "disclosure": {
                      "required": true,
                      "regulation": "eu_ai_act_art_50",
                      "obligation": "example-obligation",
                      "agentVerified": true
                    },
                    "issuedAt": "2026-09-13T12:00:00.000Z",
                    "ttl": 1
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/v1_InvalidApiKey"
          },
          "403": {
            "description": "Your organisation has not opted into agent verification (`feature disabled`).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "feature disabled"
                      ]
                    },
                    "requestId": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "error": "feature disabled",
                  "requestId": "req-test"
                }
              }
            }
          },
          "404": {
            "description": "Agent Passports are not enabled for this deployment. The body is `{\"error\":\"Not found\"}`, returned before the API key is checked.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "Not found"
                      ]
                    },
                    "requestId": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "error": "Not found",
                  "requestId": "req-test"
                }
              }
            }
          },
          "413": {
            "description": "`Payload too large` — the request body exceeded the size limit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/v1_RateLimited"
          },
          "500": {
            "description": "Unexpected fault.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "503": {
            "description": "The signing key is unavailable or invalid (fail-closed: there is no silent fallback to another key).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/agent/verify": {
      "post": {
        "operationId": "postAgentVerify",
        "tags": [
          "Agent Trust"
        ],
        "summary": "Verify a Web Bot Auth agent signature",
        "description": "Your backend forwards an incoming request's signature headers and target URL. Noxtica verifies the Web Bot Auth (RFC 9421) signature and joins the verdict to your organisation's agent policy registry for an allow or deny decision.\n\nVerification fails open end to end: any fault yields verdict `unsigned` and `matchedAction: null`. The endpoint is advisory and never blocks an agent itself. A structurally matched but unverified identity can never receive a binary `allow` (it is withheld to `null`), and a graduated `allow` is downgraded to `challenge`.\n\nSome response fields are additive and appear only when the matching capability is enabled for your organisation: `kya` and `policyAction` (the graduated ladder) and `disclosure` (EU AI Act Article 50 disclosure, only for a detected or verified agent).",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "read:device"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "headers"
                ],
                "properties": {
                  "headers": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "string"
                    },
                    "description": "The forwarded Web Bot Auth signature headers (`signature-input`, `signature`, `signature-agent`)."
                  },
                  "url": {
                    "type": "string",
                    "format": "uri",
                    "description": "The signed target URI the signature covers."
                  },
                  "attestation": {
                    "type": "object",
                    "properties": {
                      "tier": {
                        "type": "string",
                        "enum": [
                          "hardware",
                          "software",
                          "suspicious",
                          "unavailable",
                          "failed"
                        ]
                      },
                      "anchored": {
                        "type": "boolean"
                      }
                    }
                  },
                  "riskBand": {
                    "type": "string",
                    "enum": [
                      "critical",
                      "high",
                      "medium",
                      "low",
                      "minimal"
                    ]
                  },
                  "jti": {
                    "type": "string",
                    "description": "Device-correlated token id; when graduated agent policy is enabled for your organisation and it has registry rows, it completes an `agent_attestation_chain` link."
                  }
                }
              },
              "example": {
                "headers": {
                  "key": "example-headers"
                },
                "url": "https://verify.noxtica.com/s/kycs.tenant_42.9f3a8b7c6d5e4f3a2b1c0d9e8f7a6b5c",
                "attestation": {
                  "tier": "hardware",
                  "anchored": true
                },
                "riskBand": "critical",
                "jti": "example-jti"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "A resolved Web Bot Auth verdict plus the KYA registry join.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "verdict",
                    "keyid",
                    "signatureAgent",
                    "matchedAction"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "verdict": {
                      "type": "string",
                      "enum": [
                        "verified",
                        "unsigned",
                        "invalid_signature",
                        "expired",
                        "replay"
                      ]
                    },
                    "keyid": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "signatureAgent": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "matchedAction": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "enum": [
                        "allow",
                        "deny"
                      ]
                    },
                    "attestation": {
                      "type": "object",
                      "description": "Present ONLY when the caller forwarded a valid `tier`.",
                      "properties": {
                        "tier": {
                          "type": "string",
                          "enum": [
                            "hardware",
                            "software",
                            "suspicious",
                            "unavailable",
                            "failed"
                          ]
                        },
                        "anchored": {
                          "type": "boolean"
                        },
                        "provenance": {
                          "type": "string",
                          "enum": [
                            "caller_attested"
                          ],
                          "description": "Always `caller_attested` — this handler never independently corroborates the forwarded tier."
                        }
                      }
                    },
                    "riskBand": {
                      "type": "string",
                      "enum": [
                        "critical",
                        "high",
                        "medium",
                        "low",
                        "minimal"
                      ]
                    },
                    "kya": {
                      "type": "object",
                      "description": "Present only when graduated agent policy is enabled for your organisation.",
                      "properties": {
                        "verified": {
                          "type": "boolean"
                        },
                        "agentId": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "source": {
                          "type": "string",
                          "enum": [
                            "web-bot-auth",
                            "skyfire"
                          ]
                        },
                        "attestationTier": {
                          "type": "string",
                          "enum": [
                            "hardware",
                            "software",
                            "suspicious",
                            "unavailable",
                            "failed"
                          ]
                        },
                        "attestationTierProvenance": {
                          "type": "string",
                          "enum": [
                            "caller_attested"
                          ]
                        },
                        "cfVerified": {
                          "type": "boolean",
                          "description": "Present ONLY on a Cloudflare Verified AI Agents match."
                        },
                        "cfVerifiedName": {
                          "type": "string"
                        },
                        "trustCaveat": {
                          "type": "string",
                          "enum": [
                            "structural_only_signature_unverified"
                          ],
                          "description": "Present ONLY when the identity came from the Skyfire interop adapter."
                        }
                      }
                    },
                    "disclosure": {
                      "type": "object",
                      "description": "Present only when EU AI Act disclosure is enabled for your organisation and a detected or verified agent is present.",
                      "properties": {
                        "required": {
                          "type": "boolean",
                          "enum": [
                            true
                          ]
                        },
                        "regulation": {
                          "type": "string",
                          "enum": [
                            "eu_ai_act_art_50"
                          ]
                        },
                        "obligation": {
                          "type": "string"
                        },
                        "agentVerified": {
                          "type": "boolean"
                        }
                      }
                    },
                    "policyAction": {
                      "type": "string",
                      "enum": [
                        "allow",
                        "observe",
                        "challenge",
                        "deny"
                      ],
                      "description": "Present only when graduated agent policy is enabled for your organisation and an attributable identity exists — the advisory graduated enforcement tier (Noxtica never acts on it)."
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "verdict": "verified",
                  "keyid": "example-keyid",
                  "signatureAgent": "example-signatureAgent",
                  "matchedAction": "allow",
                  "attestation": {
                    "tier": "hardware",
                    "anchored": true,
                    "provenance": "caller_attested"
                  },
                  "riskBand": "critical",
                  "kya": {
                    "verified": true,
                    "agentId": "example-agentId",
                    "source": "web-bot-auth",
                    "attestationTier": "hardware",
                    "attestationTierProvenance": "caller_attested",
                    "cfVerified": true,
                    "cfVerifiedName": "example-cfVerifiedName",
                    "trustCaveat": "structural_only_signature_unverified"
                  },
                  "disclosure": {
                    "required": true,
                    "regulation": "eu_ai_act_art_50",
                    "obligation": "example-obligation",
                    "agentVerified": true
                  },
                  "policyAction": "allow"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/v1_InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/v1_InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/v1_ScopeForbidden"
          },
          "413": {
            "$ref": "#/components/responses/v1_BodyTooLarge"
          },
          "415": {
            "description": "`Content-Type must be application/json`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/v1_RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/ip/reputation": {
      "post": {
        "operationId": "postIpReputation",
        "tags": [
          "IP & Risk Scoring"
        ],
        "summary": "Look up IP reputation",
        "description": "Returns the reputation verdict `{category, source, confidence}` for one IP address supplied by your backend, from the same feed Noxtica uses to score its own submissions. When the address is not listed the response is `listed: false`; an unlisted address, an empty feed or a lookup fault never produces an error.\n\nThe queried IP is echoed back in the response, which is your own input. It is not stored or logged unless your organisation has opted into raw-IP storage; only the derived verdict is retained. A served call counts toward your organisation's IP-reputation usage.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "read:device"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "ip"
                ],
                "properties": {
                  "ip": {
                    "type": "string",
                    "description": "An IPv4 dotted-quad or IPv6 address."
                  }
                }
              },
              "example": {
                "ip": "example-ip"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The derived reputation verdict, or `listed:false` when the engine has no signal.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "ip",
                    "listed"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "ip": {
                      "type": "string",
                      "description": "Echoed back verbatim (the caller's own query input)."
                    },
                    "listed": {
                      "type": "boolean"
                    },
                    "verdict": {
                      "type": "object",
                      "description": "Present ONLY when `listed` is true.",
                      "properties": {
                        "category": {
                          "type": "string"
                        },
                        "source": {
                          "type": "string"
                        },
                        "confidence": {
                          "type": "number"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "ip": "example-ip",
                  "listed": true,
                  "verdict": {
                    "category": "example-category",
                    "source": "example-source",
                    "confidence": 1
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/v1_InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/v1_InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/v1_ScopeForbidden"
          },
          "429": {
            "$ref": "#/components/responses/v1_RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/score": {
      "post": {
        "operationId": "postScore",
        "tags": [
          "IP & Risk Scoring"
        ],
        "summary": "Score a signals payload",
        "description": "Scores an already-collected `signals` payload from your backend and returns the headline score, confidence, tier and flags that the Noxtica collector computes for its own submissions. Call it from a server with an `sk_` key that carries the `read:device` scope (the default scope of every key); never from a browser.\n\n**Request.** Send either the complete enriched payload `{\"signals\": {...}, \"serverSideSignals\": {...}, ...}` or, for older callers, the inner `signals` object on its own, which is wrapped once. The body may be up to 256 KiB. The raw payload is not logged.\n\n**Response.** `score` is the engine's score, `tier` its risk band and `flags` the flags that fired. `confidence` is an integer from 0 to 100 (50 is neutral). `attestation` is always `null` on this route: the payload is supplied by the caller and cannot be trusted as hardware evidence, so no hardware-verification claim is ever made.\n\n**Allowance.** Calls within your plan's monthly Score API allowance are included. Beyond it the score is still served and the response carries a `nudge` object with `code: free_tier_exceeded`; the score is never withheld.\n\n**Errors.** `400` `Invalid body` when the body is not a JSON object or is larger than 256 KiB, and `Invalid signals` when `signals` is present but is not an object; `401`, `403`, `429` and `500` as on every key-authenticated route. No `413` is returned: an oversized body is a `400`.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "read:device"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "The documented form is the complete enriched payload (`{ signals: {...}, serverSideSignals?: {...}, ... }`) submit scores; a legacy caller MAY instead POST the inner `signals` object directly and it is wrapped exactly once.",
                "additionalProperties": true
              },
              "example": {}
            }
          }
        },
        "responses": {
          "200": {
            "description": "The re-scored verdict, mapped onto the public 0-100 confidence scale.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "score",
                    "confidence",
                    "tier",
                    "flags",
                    "attestation"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "score": {
                      "type": "number"
                    },
                    "confidence": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 100,
                      "description": "Normalised to 0-100 (the engine's native value is 0-1), matching `/v1/attest/verify`'s scale."
                    },
                    "tier": {
                      "type": "string",
                      "description": "The engine's `riskLevel` band."
                    },
                    "flags": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "attestation": {
                      "type": "null",
                      "description": "ALWAYS `null` on this surface — see the honesty-gate note above."
                    },
                    "nudge": {
                      "type": "object",
                      "description": "Present ONLY once the free monthly allotment is exceeded — informational only, never withholds the score.",
                      "properties": {
                        "code": {
                          "type": "string",
                          "enum": [
                            "free_tier_exceeded"
                          ]
                        },
                        "message": {
                          "type": "string"
                        },
                        "free_serving_allotment": {
                          "type": "integer"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "score": 1,
                  "confidence": 0,
                  "tier": "example-tier",
                  "flags": [
                    "example-flags"
                  ],
                  "attestation": null,
                  "nudge": {
                    "code": "free_tier_exceeded",
                    "message": "example-message",
                    "free_serving_allotment": 1
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/v1_InvalidRequest"
          },
          "401": {
            "$ref": "#/components/responses/v1_InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/v1_ScopeForbidden"
          },
          "429": {
            "$ref": "#/components/responses/v1_RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/protected-actions/verify": {
      "post": {
        "operationId": "postProtectedActionsVerify",
        "tags": [
          "Protected Actions"
        ],
        "summary": "Redeem a protected-action request id",
        "description": "Call this from your backend before letting a protected action (login, sign-up, checkout, ...) proceed. Send the `requestId` your browser integration obtained for the action: the resolved value of `noxticaClient.protect(name)`, the hidden `nox_request_id` input of a `data-nox-protect` form, or `form.dataset.noxRequestId` / the `noxtica:protected` event of a script-submitted form. Use an `sk_` key with the `read:device` scope, the default scope of every key.\n\n**Single use inside a 300-second window.** The first valid call consumes the receipt and answers `200` with `consumed: true`. A replay inside the window is `409 already_consumed`. An unknown, expired or other-organisation id is `404 request_not_found`, and after 300 seconds every id is `404`.\n\n**Binding.** `action` is required: an id minted for `login` never satisfies a `checkout` check (`422 action_mismatch`; the receipt is not consumed). `expectedDomain` (a hostname, origin or URL) additionally binds the page that ran the action (`422 domain_mismatch`; not consumed). A request that arrives without a `requestId` (a fail-open timeout, a blocked script) means \"no client signal\", never a pass.\n\n**Result.** `verdict` is the risk band (`minimal`, `low`, `medium`, `high`, `critical`); `score` (higher is riskier) and `confidence` (0 to 1) are the values the browser received, and this server-to-server call always returns them. The request body is limited to 2048 bytes. A `500` carries no `ok` field and never consumes the receipt.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "read:device"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "requestId",
                  "action"
                ],
                "properties": {
                  "requestId": {
                    "type": "string",
                    "format": "uuid",
                    "description": "The protected submission's request id."
                  },
                  "action": {
                    "type": "string",
                    "pattern": "^[a-z][a-z0-9_-]{0,31}$",
                    "description": "The protected action name the tenant expects (`login`, `checkout`, ...)."
                  },
                  "expectedDomain": {
                    "type": "string",
                    "maxLength": 269,
                    "description": "Optional hostname/origin/URL the action must have run on."
                  }
                }
              },
              "example": {
                "requestId": "8f1c2a52-6a6e-4b0e-9d52-2a7c1d9e4b10",
                "action": "login",
                "expectedDomain": "www.example.com"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The receipt was valid and has now been consumed.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "requestId",
                    "action",
                    "fingerprintId",
                    "verdict",
                    "score",
                    "confidence",
                    "domain",
                    "issuedAt",
                    "expiresAt",
                    "consumed",
                    "consumedAt"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "requestId": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "action": {
                      "type": "string"
                    },
                    "fingerprintId": {
                      "type": "string",
                      "description": "The device id of the protected submission (the same value the dashboard keys on)."
                    },
                    "verdict": {
                      "type": "string",
                      "enum": [
                        "minimal",
                        "low",
                        "medium",
                        "high",
                        "critical"
                      ]
                    },
                    "score": {
                      "type": "number"
                    },
                    "confidence": {
                      "type": "number",
                      "minimum": 0,
                      "maximum": 1
                    },
                    "domain": {
                      "type": "string",
                      "description": "Hostname of the page that ran the action."
                    },
                    "issuedAt": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "expiresAt": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "consumed": {
                      "type": "boolean",
                      "enum": [
                        true
                      ],
                      "description": "This call consumed the receipt."
                    },
                    "consumedAt": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "requestId": "8f1c2a52-6a6e-4b0e-9d52-2a7c1d9e4b10",
                  "action": "login",
                  "fingerprintId": "a1b2c3d4e5f60718293a4b5c6d7e8f90",
                  "verdict": "low",
                  "score": 12,
                  "confidence": 0.91,
                  "domain": "www.example.com",
                  "issuedAt": "2026-10-08T10:00:00.000Z",
                  "expiresAt": "2026-10-08T10:05:00.000Z",
                  "consumed": true,
                  "consumedAt": "2026-10-08T10:00:02.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_body`, `invalid_request_id`, `invalid_action` or `invalid_expected_domain`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProtectedActionVerifyError"
                },
                "example": {
                  "ok": false,
                  "error": "invalid_request_id",
                  "requestId": "req-test"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/v1_InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/v1_ScopeForbidden"
          },
          "404": {
            "description": "`request_not_found` — unknown, expired (older than 300 s) or minted for another tenant.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProtectedActionVerifyError"
                },
                "example": {
                  "ok": false,
                  "error": "request_not_found",
                  "requestId": "req-test"
                }
              }
            }
          },
          "409": {
            "description": "`already_consumed` — the receipt was already redeemed (replay inside the window).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProtectedActionVerifyError"
                },
                "example": {
                  "ok": false,
                  "error": "already_consumed",
                  "consumed": true,
                  "consumedAt": "2026-10-08T10:00:02.000Z",
                  "requestId": "req-test"
                }
              }
            }
          },
          "413": {
            "description": "`payload_too_large` — over the 2048-byte cap.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProtectedActionVerifyError"
                },
                "example": {
                  "ok": false,
                  "error": "payload_too_large",
                  "requestId": "req-test"
                }
              }
            }
          },
          "422": {
            "description": "`action_mismatch` or `domain_mismatch` — the receipt is NOT consumed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProtectedActionVerifyError"
                },
                "example": {
                  "ok": false,
                  "error": "action_mismatch",
                  "requestId": "req-test"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/v1_RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/attest/android": {
      "post": {
        "operationId": "postAttestAndroid",
        "tags": [
          "Device Attestation"
        ],
        "summary": "Android Play Integrity attestation (mint / verify)",
        "description": "Server-to-server relay for Android Play Integrity attestation. Your backend — typically the backend-for-frontend a mobile app authenticates to — calls this route with an `sk_` key; the mobile app never calls it directly. Two actions are supported:\n\n1. `{\"action\":\"mint\"}` returns a single-use nonce, valid for 300 seconds and bound to your organisation and domain, that the app binds a Play Integrity standard token to.\n2. `{\"action\":\"verify\",\"nonce\":\"...\",\"token\":\"...\"}` (the older field name `integrityToken` is also accepted) claims the nonce exactly once, verifies the token with Google's Play Integrity service, records the result and returns the verdict. A `risk.flagged` webhook may be sent to subscribed endpoints.\n\n`{\"action\":\"assert\"}` is iOS-only and is refused on this route with the `GatedNotFound` 404. When verification with Google cannot complete, the verifier fails closed to `verificationLevel: \"unverified\"`: the result is stored but no verification credit is implied, and an unverified result is never silently upgraded.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "read:device"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "action": {
                    "type": "string",
                    "enum": [
                      "mint",
                      "verify"
                    ],
                    "default": "verify"
                  },
                  "domain_id": {
                    "type": "string",
                    "description": "OPTIONAL tenant-owned domain the nonce/claim is bound to."
                  },
                  "nonce": {
                    "type": "string",
                    "description": "REQUIRED for `verify` — the nonce returned by a prior `mint`."
                  },
                  "token": {
                    "type": "string",
                    "description": "REQUIRED for `verify` — the Play Integrity STANDARD token (also accepted under the legacy key `integrityToken`)."
                  }
                }
              },
              "example": {
                "action": "mint",
                "domain_id": "dom_3f2a8c91d6e5f470",
                "nonce": "nonce_5f3a8c1e2d4b6f709182a3b4c5d6e7f8",
                "token": "tok_9f2a1c3e5d7b4a6f8091c2d3e4f5a6b7"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The mint or verify outcome. A mint returns `{ok,nonce,ttlSeconds,platform}`; a verify returns `{ok,verdict,verificationLevel,platform,attestationId?}` (`attestationId` present only once a PostgreSQL authority row is recorded; `verdict:'error'` signals a recording fault, not a failed proof). IMPORTANT: `ok:true` is only the envelope-level \"request handled\" flag for BOTH mint and verify — it is present, and true, even when a `verify` call correctly REJECTS a forged/invalid token (fail-closed discipline; this route never returns a 4xx for a bad token). It is never a statement about the attestation's outcome. To determine pass/fail, check `verdict` (only ever `'pass'` when `verificationLevel` is `'verified'`) and `verificationLevel`, never `ok`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "platform"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ],
                      "description": "Envelope-only \"request handled\" flag — always true on this 200 path for BOTH mint and a correctly-refused verify. NOT a verdict; check `verdict`/`verificationLevel` for the actual attestation outcome."
                    },
                    "platform": {
                      "type": "string",
                      "enum": [
                        "android"
                      ]
                    },
                    "nonce": {
                      "type": "string"
                    },
                    "ttlSeconds": {
                      "type": "integer"
                    },
                    "verdict": {
                      "type": "string",
                      "enum": [
                        "pass",
                        "fail",
                        "error",
                        "indeterminate"
                      ]
                    },
                    "verificationLevel": {
                      "type": "string",
                      "description": "e.g. `verified` / `unverified`."
                    },
                    "attestationId": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "platform": "android",
                  "nonce": "nonce_5f3a8c1e2d4b6f709182a3b4c5d6e7f8",
                  "ttlSeconds": 3600,
                  "verdict": "pass",
                  "verificationLevel": "verified",
                  "attestationId": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
                }
              }
            }
          },
          "400": {
            "description": "`Missing nonce / token`, `Invalid Content-Length header`, or `Invalid JSON body`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/v1_InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/v1_ScopeForbidden"
          },
          "404": {
            "$ref": "#/components/responses/v1_GatedNotFound"
          },
          "413": {
            "$ref": "#/components/responses/v1_BodyTooLarge"
          },
          "415": {
            "description": "`Content-Type must be application/json`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/v1_RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "description": "`Could not mint challenge` — the tenant edge authority / single-use token store is unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/attest/ios": {
      "post": {
        "operationId": "postAttestIos",
        "tags": [
          "Device Attestation"
        ],
        "summary": "iOS App Attest attestation (mint / verify / assert)",
        "description": "Server-to-server relay for iOS App Attest, with the same posture as `POST /v1/attest/android`: your backend calls it with an `sk_` key and the app never does. Three actions are supported:\n\n1. `{\"action\":\"mint\"}` returns a single-use nonce, valid for 300 seconds, that the app generates an App Attest key and attestation over.\n2. `{\"action\":\"verify\",\"nonce\":\"...\",\"token\":\"...\"}` (the older field name `attestationObject` is also accepted) parses the attestation object, checks the nonce binding, records the result, may send a `risk.flagged` webhook and returns the verdict. Verification currently covers structure, `rpIdHash` and nonce binding (`verificationLevel: \"structure_only\"`); promotion to `verified` additionally requires certificate-chain validation against pinned Apple intermediate key material, which is available only when it is configured for the deployment.\n3. `{\"action\":\"assert\",\"nonce\":\"...\",\"assertion\":\"...\",\"keyId\":\"...\"}` is a destructive account-deletion possession proof, available only when it is enabled for your organisation (otherwise the `GatedNotFound` 404). It verifies an App Attest assertion against the stored enrollment binding for `keyId`, enforces a monotonic sign counter (replay defence) and on success returns the bound `subjectId` and the fixed `actionScope`. The nonce is consumed even when the assertion fails.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "read:device"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "action": {
                    "type": "string",
                    "enum": [
                      "mint",
                      "verify",
                      "assert"
                    ],
                    "default": "verify"
                  },
                  "domain_id": {
                    "type": "string"
                  },
                  "nonce": {
                    "type": "string",
                    "description": "REQUIRED for `verify`/`assert` — the nonce returned by a prior `mint`."
                  },
                  "token": {
                    "type": "string",
                    "description": "REQUIRED for `verify` — the base64 CBOR App Attest attestation object (also accepted under the legacy key `attestationObject`)."
                  },
                  "assertion": {
                    "type": "string",
                    "description": "REQUIRED for `assert` — the base64url App Attest assertion CBOR."
                  },
                  "keyId": {
                    "type": "string",
                    "description": "REQUIRED for `assert` — the App Attest key id from the prior enrollment (`verify`) response."
                  }
                }
              },
              "example": {
                "action": "mint",
                "domain_id": "dom_3f2a8c91d6e5f470",
                "nonce": "nonce_5f3a8c1e2d4b6f709182a3b4c5d6e7f8",
                "token": "tok_9f2a1c3e5d7b4a6f8091c2d3e4f5a6b7",
                "assertion": "example-assertion",
                "keyId": "example-keyId"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The mint / verify / assert outcome. A successful `assert` additionally carries `subjectId` (server-resolved from the stored binding — never request-derived). IMPORTANT: `ok:true` is only the envelope-level \"request handled\" flag for mint/verify/assert alike — it is present, and true, even when a `verify` call correctly REJECTS a forged/invalid attestation object (fail-closed discipline; this route never returns a 4xx for a bad token). It is never a statement about the attestation's outcome. To determine pass/fail, check `verdict` (only ever `'pass'` when `verificationLevel` is `'verified'`) and `verificationLevel`, never `ok`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "platform"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ],
                      "description": "Envelope-only \"request handled\" flag — always true on this 200 path for mint/verify/assert alike, including a correctly-refused verify. NOT a verdict; check `verdict`/`verificationLevel` for the actual attestation outcome."
                    },
                    "platform": {
                      "type": "string",
                      "enum": [
                        "ios"
                      ]
                    },
                    "nonce": {
                      "type": "string"
                    },
                    "ttlSeconds": {
                      "type": "integer"
                    },
                    "verdict": {
                      "type": "string",
                      "enum": [
                        "pass",
                        "fail",
                        "error",
                        "indeterminate"
                      ]
                    },
                    "verificationLevel": {
                      "type": "string"
                    },
                    "attestationId": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "platform": "ios",
                  "nonce": "nonce_5f3a8c1e2d4b6f709182a3b4c5d6e7f8",
                  "ttlSeconds": 3600,
                  "verdict": "pass",
                  "verificationLevel": "verified",
                  "attestationId": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
                }
              }
            }
          },
          "400": {
            "description": "`Missing nonce / token`, `Missing nonce / assertion / keyId`, `Invalid Content-Length header`, or `Invalid JSON body`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/v1_InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/v1_ScopeForbidden"
          },
          "404": {
            "$ref": "#/components/responses/v1_GatedNotFound"
          },
          "413": {
            "$ref": "#/components/responses/v1_BodyTooLarge"
          },
          "415": {
            "description": "`Content-Type must be application/json`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/v1_RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "description": "`Could not mint challenge`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/attest/verify": {
      "post": {
        "operationId": "postAttestVerify",
        "tags": [
          "Device Attestation"
        ],
        "summary": "Verify a CPU/GPU attestation proof",
        "description": "Returns a synchronous verdict for a one-off CPU/GPU proof-of-work attestation, driven by your backend on behalf of its web client outside the normal `/client/submit` flow. `{\"action\":\"verify\",\"challengeId\":\"...\",\"proof\":{...}}` redeems a challenge minted by `POST /v1/attest/challenge`.\n\nNot enabled by default: when the capability is not enabled for your organisation this route does not answer 404: it fails open to a neutral HTTP 200. When the capability is not enabled, or on any internal fault, the response is `{\"ok\":true,\"featureEnabled\":false,\"tier\":\"unavailable\",\"confidence\":50,\"anchored\":false}`. \"No signal\" is always a pass-through, never an outage.\n\nAbsence is not a penalty: a proof that reports no CPU/GPU capability scores neutral. Only a proof that is present but rejected (after a successful single-use nonce claim) is a `failed` signal, and every rejected proof collapses to the same public reason `verification_rejected`. The literal tier `hardware` is published only when publication of the hardware attestation level is enabled for your organisation; otherwise `hardware` and `software` are both reported as `attested`.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "read:device"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "action": {
                    "type": "string",
                    "enum": [
                      "verify"
                    ],
                    "default": "verify",
                    "description": "This path always defaults/forces `verify`; use `POST /v1/attest/challenge` to mint."
                  },
                  "domain_id": {
                    "type": "string"
                  },
                  "kind": {
                    "type": "string",
                    "enum": [
                      "gpu",
                      "cpu"
                    ],
                    "default": "gpu"
                  },
                  "challengeId": {
                    "type": "string",
                    "description": "REQUIRED — the `challengeId` returned by a prior `POST /v1/attest/challenge`."
                  },
                  "proof": {
                    "type": "object",
                    "additionalProperties": true,
                    "description": "The CPU/GPU attestation proof payload narrowed by `narrowProof` against the obsidian VM's engine-internal proof shape. Left open (`additionalProperties: true`) — the exact engine field set (`adapterInfo`, ULP samples, raw multichannel evidence, etc.) is internal wire format with no independent public contract and is not safely documented from the handler alone."
                  }
                }
              },
              "example": {
                "action": "verify",
                "domain_id": "dom_3f2a8c91d6e5f470",
                "kind": "gpu",
                "challengeId": "chal_3c9b2f7e4a3d4c8e",
                "proof": {}
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Either the NEUTRAL feature-off/fail-open band, or a scored verdict with the M3-masked published tier.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "featureEnabled",
                    "tier",
                    "confidence",
                    "anchored",
                    "reasons",
                    "verifiedAt"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "featureEnabled": {
                      "type": "boolean"
                    },
                    "tier": {
                      "type": "string",
                      "enum": [
                        "hardware",
                        "software",
                        "attested",
                        "suspicious",
                        "failed",
                        "unavailable"
                      ]
                    },
                    "confidence": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 100
                    },
                    "anchored": {
                      "type": "boolean"
                    },
                    "reasons": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "verifiedAt": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "featureEnabled": true,
                  "tier": "hardware",
                  "confidence": 0,
                  "anchored": true,
                  "reasons": [
                    "example-reasons"
                  ],
                  "verifiedAt": "2026-09-13T12:00:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`Invalid Content-Length header` or `Invalid JSON body`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/v1_InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/v1_ScopeForbidden"
          },
          "413": {
            "$ref": "#/components/responses/v1_BodyTooLarge"
          },
          "415": {
            "description": "`Content-Type must be application/json`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/v1_RateLimited"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/attest/challenge": {
      "post": {
        "operationId": "postAttestChallenge",
        "tags": [
          "Device Attestation"
        ],
        "summary": "Mint a CPU/GPU attestation challenge",
        "description": "Mints a single-use, organisation- and domain-bound, origin-anchored challenge and returns the directive your client feeds to the attestation runtime. The URL path forces `action: \"challenge\"` whatever the body says. Redeem the returned `challengeId` at `POST /v1/attest/verify`.\n\nThe availability and fail-open posture are the same as for `POST /v1/attest/verify`: a missing `Origin` header, an authority fault or a missing integrity pin all collapse to `{\"ok\":true,\"featureEnabled\":true,\"challenge\":null,\"reason\":\"challenge_unavailable\"}` with HTTP 200, never a 5xx.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "read:device"
            ]
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "domain_id": {
                    "type": "string"
                  },
                  "kind": {
                    "type": "string",
                    "enum": [
                      "gpu",
                      "cpu"
                    ],
                    "default": "gpu"
                  }
                }
              },
              "example": {
                "domain_id": "dom_3f2a8c91d6e5f470",
                "kind": "gpu"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "A minted challenge directive, or the neutral `challenge_unavailable` refusal.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "featureEnabled",
                    "verifiedAt"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "featureEnabled": {
                      "type": "boolean"
                    },
                    "reason": {
                      "type": "string",
                      "enum": [
                        "challenge_unavailable",
                        "attest_verify_disabled",
                        "attest_verify_tenant_disabled"
                      ]
                    },
                    "challenge": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "properties": {
                        "challengeId": {
                          "type": "string"
                        },
                        "nonce": {
                          "type": "string"
                        },
                        "loaderUrl": {
                          "type": "string",
                          "format": "uri"
                        },
                        "wasmUrl": {
                          "type": "string",
                          "format": "uri"
                        },
                        "wasmSha256": {
                          "type": "string"
                        },
                        "seed": {
                          "type": "string"
                        },
                        "level": {
                          "type": "integer"
                        },
                        "rawEvidenceCommitmentVersion": {
                          "type": "integer"
                        },
                        "expiresAt": {
                          "type": "integer",
                          "description": "Epoch milliseconds."
                        }
                      }
                    },
                    "verifiedAt": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "featureEnabled": true,
                  "reason": "challenge_unavailable",
                  "challenge": {
                    "challengeId": "chal_3c9b2f7e4a3d4c8e",
                    "nonce": "nonce_5f3a8c1e2d4b6f709182a3b4c5d6e7f8",
                    "loaderUrl": "https://example.com",
                    "wasmUrl": "https://example.com",
                    "wasmSha256": "example-wasmSha256",
                    "seed": "seed-01",
                    "level": 1,
                    "rawEvidenceCommitmentVersion": 1,
                    "expiresAt": 1768435200
                  },
                  "verifiedAt": "2026-09-13T12:00:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`Invalid Content-Length header` or `Invalid JSON body`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/v1_InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/v1_ScopeForbidden"
          },
          "413": {
            "$ref": "#/components/responses/v1_BodyTooLarge"
          },
          "415": {
            "description": "`Content-Type must be application/json`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/v1_RateLimited"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/integrity/verify": {
      "post": {
        "operationId": "postIntegrityVerify",
        "tags": [
          "Web/App Integrity"
        ],
        "summary": "Combined web/webview integrity verdict",
        "description": "Combines three existing signals into one integrity verdict for a web or webview session; it adds no new scoring path: (1) the CPU/GPU attestation verdict, from an optional `challengeId` / `proof` pair where absence is neutral, (2) the calibrated risk score over a caller-supplied `signals` payload, and (3) the virtualization-corroboration marker read from the score's flags.\n\nNot enabled by default. When the capability is not enabled for your organisation, or on any fault, the route fails open to a neutral HTTP 200 `{\"ok\":true,\"integrity\":\"unverified\",\"signals\":{\"attestation\":\"unavailable\",\"virtualization\":\"unavailable\",\"score\":\"minimal\"},\"confidence\":50}`; it never answers 5xx or 404. The `attestation` label is masked exactly as on `POST /v1/attest/verify`.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "read:device"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "domain_id": {
                    "type": "string"
                  },
                  "kind": {
                    "type": "string",
                    "enum": [
                      "gpu",
                      "cpu"
                    ],
                    "default": "gpu"
                  },
                  "challengeId": {
                    "type": "string",
                    "description": "OPTIONAL — a prior `/v1/attest/challenge` id; absence skips the attestation leg (neutral)."
                  },
                  "proof": {
                    "type": "object",
                    "additionalProperties": true,
                    "description": "OPTIONAL CPU/GPU attestation proof, same internal wire shape as `/v1/attest/verify`'s `proof` — left open for the same reason."
                  },
                  "signals": {
                    "type": "object",
                    "additionalProperties": true,
                    "description": "The caller-supplied calibrated-score signals payload (same lenient envelope as `/v1/score` — accepts `{signals:{...}}` or a bare object)."
                  }
                }
              },
              "example": {
                "domain_id": "dom_3f2a8c91d6e5f470",
                "kind": "gpu",
                "challengeId": "chal_3c9b2f7e4a3d4c8e",
                "proof": {},
                "signals": {}
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The combined integrity verdict, or the neutral feature-off/fail-open band.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "featureEnabled",
                    "integrity",
                    "signals",
                    "confidence",
                    "verifiedAt"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "featureEnabled": {
                      "type": "boolean"
                    },
                    "integrity": {
                      "type": "string",
                      "enum": [
                        "trusted",
                        "suspicious",
                        "unverified"
                      ]
                    },
                    "signals": {
                      "type": "object",
                      "properties": {
                        "attestation": {
                          "type": "string",
                          "enum": [
                            "hardware",
                            "software",
                            "attested",
                            "suspicious",
                            "failed",
                            "unavailable"
                          ]
                        },
                        "virtualization": {
                          "type": "string",
                          "enum": [
                            "corroborated",
                            "unavailable"
                          ]
                        },
                        "score": {
                          "type": "string",
                          "description": "The calibrated engine's `riskLevel` band."
                        }
                      }
                    },
                    "confidence": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 100
                    },
                    "reason": {
                      "type": "string",
                      "description": "Present only on the neutral/feature-off band (e.g. noxtrust_disabled, noxtrust_tenant_disabled, tenant_db_unavailable, score_fault_neutral, internal_neutral)."
                    },
                    "verifiedAt": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "featureEnabled": true,
                  "integrity": "trusted",
                  "signals": {
                    "attestation": "hardware",
                    "virtualization": "corroborated",
                    "score": "example-score"
                  },
                  "confidence": 0,
                  "reason": "user_requested",
                  "verifiedAt": "2026-09-13T12:00:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`Invalid Content-Length header`, `Invalid JSON body`, or `Invalid body`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/v1_InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/v1_ScopeForbidden"
          },
          "413": {
            "$ref": "#/components/responses/v1_BodyTooLarge"
          },
          "415": {
            "description": "`Content-Type must be application/json`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/v1_RateLimited"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/app-config": {
      "post": {
        "operationId": "postAppConfig",
        "tags": [
          "Mobile App Config"
        ],
        "summary": "Forced-update and kill-switch decision for an app launch",
        "description": "Server-to-server call from your backend (for example the backend-for-frontend a mobile app authenticates to) that decides one launch outcome for a mobile app. Send `platform`, `appVersion` and, on Android, the client-asserted Play Integrity `appRecognitionVerdict`. The first rule that applies wins:\n\n1. `reason: \"killed\"` — an emergency kill switch is active.\n2. `reason: \"forced_update\"` — `appVersion` is below the minimum version configured for the platform. This is a forced-update nudge, not an anti-tamper control: a patched app can report any version.\n3. `reason: \"app_not_recognized\"` — Android only, when `appRecognitionVerdict` is not `PLAY_RECOGNIZED`; a missing verdict counts as not recognised. This is advisory: the verdict is client-asserted and is not verified with Google, unlike `/v1/attest/android`. iOS is exempt.\n\nOtherwise `reason: \"ok\"`. Every decision is audited with coarse, non-personal facts. The request body is limited to 1024 bytes.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "read:device"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "platform",
                  "appVersion"
                ],
                "properties": {
                  "platform": {
                    "type": "string",
                    "enum": [
                      "android",
                      "ios"
                    ]
                  },
                  "appVersion": {
                    "type": "string"
                  },
                  "appRecognitionVerdict": {
                    "type": "string",
                    "description": "Client-asserted Play Integrity app-recognition verdict (e.g. `PLAY_RECOGNIZED`); Android only, ADVISORY, never independently verified."
                  }
                }
              },
              "example": {
                "platform": "android",
                "appVersion": "example-appVersion",
                "appRecognitionVerdict": "example-appRecognitionVerdict"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The resolved forced-update / kill-switch decision.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "allowed",
                    "reason",
                    "minVersion"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "allowed": {
                      "type": "boolean"
                    },
                    "reason": {
                      "type": "string",
                      "enum": [
                        "ok",
                        "killed",
                        "forced_update",
                        "app_not_recognized"
                      ]
                    },
                    "minVersion": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "The operator-configured floor for this platform, or `null` when unset."
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "allowed": true,
                  "reason": "ok",
                  "minVersion": "example-minVersion"
                }
              }
            }
          },
          "400": {
            "description": "`Invalid body`, `Invalid or missing platform`, `Invalid or missing appVersion`, or `Invalid appRecognitionVerdict`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/v1_InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/v1_ScopeForbidden"
          },
          "413": {
            "description": "`Payload too large` — over the 1024-byte cap.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/v1_RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/passkey/challenge": {
      "post": {
        "operationId": "postPasskeyChallenge",
        "tags": [
          "Passkey"
        ],
        "summary": "Mint a WebAuthn ceremony challenge",
        "description": "Server-to-server (`sk_` key, scope `write:passkey`). Mints a single-use, time-limited WebAuthn ceremony challenge. You supply an opaque `subject_id`, the exact `domain_id` of one of your active domains and the ceremony `purpose` (`register` or `assert`). The subject's existence is deliberately not checked at mint time. The domain must resolve to an active route of your organisation, and its origin is bound into the challenge, which prevents a later cross-domain ceremony.\n\nNot enabled by default: when the passkey capability is not enabled for your organisation, every passkey endpoint answers the `GatedNotFound` 404.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "write:passkey"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "subject_id",
                  "domain_id",
                  "purpose"
                ],
                "properties": {
                  "subject_id": {
                    "type": "string",
                    "description": "Opaque caller-generated subject correlation id."
                  },
                  "domain_id": {
                    "type": "string",
                    "description": "The tenant's exact registered domain id this ceremony is bound to."
                  },
                  "purpose": {
                    "type": "string",
                    "enum": [
                      "register",
                      "assert"
                    ]
                  }
                }
              },
              "example": {
                "subject_id": "subj_4821",
                "domain_id": "dom_3f2a8c91d6e5f470",
                "purpose": "register"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "A minted challenge plus the WebAuthn RP/ceremony parameters, or a closed `ok:false` refusal.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "type": "object",
                      "required": [
                        "ok",
                        "challenge",
                        "purpose",
                        "ttlSeconds",
                        "rp",
                        "pubKeyCredParams"
                      ],
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "enum": [
                            true
                          ]
                        },
                        "challenge": {
                          "type": "string"
                        },
                        "purpose": {
                          "type": "string",
                          "enum": [
                            "register",
                            "assert"
                          ]
                        },
                        "ttlSeconds": {
                          "type": "integer"
                        },
                        "rp": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string",
                              "description": "The WebAuthn `rpId` derived from the tenant's registered origin."
                            },
                            "origins": {
                              "type": "array",
                              "items": {
                                "type": "string",
                                "format": "uri"
                              }
                            }
                          }
                        },
                        "pubKeyCredParams": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "type": {
                                "type": "string",
                                "enum": [
                                  "public-key"
                                ]
                              },
                              "alg": {
                                "type": "integer",
                                "description": "COSE algorithm id (ES256 -7 or RS256 -257)."
                              }
                            }
                          }
                        }
                      }
                    },
                    {
                      "type": "object",
                      "required": [
                        "ok",
                        "reason"
                      ],
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "enum": [
                            false
                          ]
                        },
                        "reason": {
                          "type": "string",
                          "enum": [
                            "invalid_request",
                            "purpose_mismatch",
                            "client_data_invalid",
                            "challenge_invalid",
                            "challenge_mismatch",
                            "origin_not_allowed",
                            "rp_id_mismatch",
                            "user_not_present",
                            "user_not_verified",
                            "attestation_invalid",
                            "attestation_signature_invalid",
                            "unsupported_algorithm",
                            "assertion_signature_invalid",
                            "sign_count_regression",
                            "subject_unverified",
                            "credential_exists",
                            "credential_unknown",
                            "storage_error",
                            "step_up_unconfigured",
                            "step_up_transport_error",
                            "step_up_provider_error",
                            "step_up_no_match",
                            "step_up_reference_required",
                            "aaguid_blocked",
                            "attestation_required",
                            "attestation_untrusted",
                            "aaguid_status_rejected",
                            "step_up_reference_replayed",
                            "step_up_claim_unavailable"
                          ]
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "ok": true,
                  "challenge": "Y2hhbGxlbmdlLW5vbmNlLTAx",
                  "purpose": "register",
                  "ttlSeconds": 3600,
                  "rp": {
                    "id": "example-id",
                    "origins": [
                      "https://example.com"
                    ]
                  },
                  "pubKeyCredParams": [
                    {
                      "type": "public-key",
                      "alg": 1
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`{\"ok\":false,\"reason\":\"invalid_request\"}` — malformed body, missing fields, or an unresolvable `domain_id`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "reason"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "reason": {
                      "type": "string",
                      "enum": [
                        "invalid_request",
                        "purpose_mismatch",
                        "client_data_invalid",
                        "challenge_invalid",
                        "challenge_mismatch",
                        "origin_not_allowed",
                        "rp_id_mismatch",
                        "user_not_present",
                        "user_not_verified",
                        "attestation_invalid",
                        "attestation_signature_invalid",
                        "unsupported_algorithm",
                        "assertion_signature_invalid",
                        "sign_count_regression",
                        "subject_unverified",
                        "credential_exists",
                        "credential_unknown",
                        "storage_error",
                        "step_up_unconfigured",
                        "step_up_transport_error",
                        "step_up_provider_error",
                        "step_up_no_match",
                        "step_up_reference_required",
                        "aaguid_blocked",
                        "attestation_required",
                        "attestation_untrusted",
                        "aaguid_status_rejected",
                        "step_up_reference_replayed",
                        "step_up_claim_unavailable"
                      ]
                    }
                  }
                },
                "example": {
                  "ok": false,
                  "reason": "invalid_request"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/v1_InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/v1_ScopeForbidden"
          },
          "404": {
            "$ref": "#/components/responses/v1_GatedNotFound"
          },
          "429": {
            "$ref": "#/components/responses/v1_RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/passkey/register": {
      "post": {
        "operationId": "postPasskeyRegister",
        "tags": [
          "Passkey"
        ],
        "summary": "Verify a WebAuthn attestation and register a passkey",
        "description": "Server-to-server (`sk_` key, scope `write:passkey`). Verifies a WebAuthn attestation and registers the credential. In order: the `register` challenge is consumed (single use); the bound subject must have an active, verified device or KYC proof; the attestation is verified against only the exact active domain bound into the challenge; an optional authenticator (AAGUID) trust policy may reject the credential before storage when it runs in enforce mode; the credential is stored against the opaque `subject_id`, with no personal data.\n\nEvery ceremony or policy refusal returns the same closed reason-code catalogue at a uniform HTTP 200 `{\"ok\":false}`, except `invalid_request` and `purpose_mismatch`, which answer 400, so a status code never reveals whether a credential exists. Availability is the same as for `POST /v1/passkey/challenge`.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "write:passkey"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "challenge",
                  "attestationObject",
                  "clientDataJSON"
                ],
                "properties": {
                  "challenge": {
                    "type": "string",
                    "description": "base64url — the challenge minted by `POST /v1/passkey/challenge` with `purpose:'register'`."
                  },
                  "attestationObject": {
                    "type": "string",
                    "description": "base64url CBOR WebAuthn attestation object."
                  },
                  "clientDataJSON": {
                    "type": "string",
                    "description": "base64url WebAuthn `clientDataJSON`."
                  },
                  "transports": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "OPTIONAL authenticator transports (e.g. `usb`, `nfc`, `internal`), persisted comma-joined."
                  }
                }
              },
              "example": {
                "challenge": "Y2hhbGxlbmdlLW5vbmNlLTAx",
                "attestationObject": "example-attestationObject",
                "clientDataJSON": "example-clientDataJSON",
                "transports": [
                  "example-transports"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The registered credential id + bound subject, or a closed `ok:false` refusal.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "type": "object",
                      "required": [
                        "ok",
                        "credentialId",
                        "subjectId"
                      ],
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "enum": [
                            true
                          ]
                        },
                        "credentialId": {
                          "type": "string"
                        },
                        "subjectId": {
                          "type": "string"
                        }
                      }
                    },
                    {
                      "type": "object",
                      "required": [
                        "ok",
                        "reason"
                      ],
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "enum": [
                            false
                          ]
                        },
                        "reason": {
                          "type": "string",
                          "enum": [
                            "invalid_request",
                            "purpose_mismatch",
                            "client_data_invalid",
                            "challenge_invalid",
                            "challenge_mismatch",
                            "origin_not_allowed",
                            "rp_id_mismatch",
                            "user_not_present",
                            "user_not_verified",
                            "attestation_invalid",
                            "attestation_signature_invalid",
                            "unsupported_algorithm",
                            "assertion_signature_invalid",
                            "sign_count_regression",
                            "subject_unverified",
                            "credential_exists",
                            "credential_unknown",
                            "storage_error",
                            "step_up_unconfigured",
                            "step_up_transport_error",
                            "step_up_provider_error",
                            "step_up_no_match",
                            "step_up_reference_required",
                            "aaguid_blocked",
                            "attestation_required",
                            "attestation_untrusted",
                            "aaguid_status_rejected",
                            "step_up_reference_replayed",
                            "step_up_claim_unavailable"
                          ]
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "ok": true,
                  "credentialId": "example-credentialId",
                  "subjectId": "subj_4821"
                }
              }
            }
          },
          "400": {
            "description": "`{\"ok\":false,\"reason\":\"invalid_request\"}` or `{\"ok\":false,\"reason\":\"purpose_mismatch\"}` — the only two reasons that map to HTTP 400.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "reason"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "reason": {
                      "type": "string",
                      "enum": [
                        "invalid_request",
                        "purpose_mismatch",
                        "client_data_invalid",
                        "challenge_invalid",
                        "challenge_mismatch",
                        "origin_not_allowed",
                        "rp_id_mismatch",
                        "user_not_present",
                        "user_not_verified",
                        "attestation_invalid",
                        "attestation_signature_invalid",
                        "unsupported_algorithm",
                        "assertion_signature_invalid",
                        "sign_count_regression",
                        "subject_unverified",
                        "credential_exists",
                        "credential_unknown",
                        "storage_error",
                        "step_up_unconfigured",
                        "step_up_transport_error",
                        "step_up_provider_error",
                        "step_up_no_match",
                        "step_up_reference_required",
                        "aaguid_blocked",
                        "attestation_required",
                        "attestation_untrusted",
                        "aaguid_status_rejected",
                        "step_up_reference_replayed",
                        "step_up_claim_unavailable"
                      ]
                    }
                  }
                },
                "example": {
                  "ok": false,
                  "reason": "invalid_request"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/v1_InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/v1_ScopeForbidden"
          },
          "404": {
            "$ref": "#/components/responses/v1_GatedNotFound"
          },
          "429": {
            "$ref": "#/components/responses/v1_RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/passkey/assert": {
      "post": {
        "operationId": "postPasskeyAssert",
        "tags": [
          "Passkey"
        ],
        "summary": "Verify a WebAuthn assertion",
        "description": "Server-to-server (`sk_` key, scope `write:passkey`). Verifies a WebAuthn assertion against a stored credential. In order: the `assert` challenge is consumed (single use) and yields the bound `subject_id`; the active credential is looked up by credential id (an unknown id gives the closed `credential_unknown`); the credential must belong to the challenge's subject (otherwise `challenge_mismatch`, so a challenge minted for subject A can never assert subject B's credential); the signature is verified over `authenticatorData || SHA-256(clientDataJSON)` with the stored public key, against only the domain bound into the challenge; the signature counter must strictly advance (otherwise `sign_count_regression`, a replay defence). On success the counter is advanced and the bound `subjectId` is returned.\n\nEvery failure returns the same uniform HTTP 200 `{\"ok\":false}`; credential-level reasons are an integrator diagnostic, not an enumeration oracle, because this surface is intra-organisation and credential ids are high-entropy. Availability is the same as for `POST /v1/passkey/challenge`.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "write:passkey"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "challenge",
                  "credentialId",
                  "authenticatorData",
                  "clientDataJSON",
                  "signature"
                ],
                "properties": {
                  "challenge": {
                    "type": "string",
                    "description": "base64url — minted with `purpose:'assert'`."
                  },
                  "credentialId": {
                    "type": "string"
                  },
                  "authenticatorData": {
                    "type": "string",
                    "description": "base64url WebAuthn `authenticatorData`."
                  },
                  "clientDataJSON": {
                    "type": "string",
                    "description": "base64url WebAuthn `clientDataJSON`."
                  },
                  "signature": {
                    "type": "string",
                    "description": "base64url WebAuthn assertion signature."
                  }
                }
              },
              "example": {
                "challenge": "Y2hhbGxlbmdlLW5vbmNlLTAx",
                "credentialId": "example-credentialId",
                "authenticatorData": "example-authenticatorData",
                "clientDataJSON": "example-clientDataJSON",
                "signature": "MEUCIQDx1F2a3B4c5D6e7F8a9B0c1D2e3F4a5B6c7D8e9F0a1B2c3D4e5F6a7B8c"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The verified bound subject, or a closed `ok:false` refusal.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "type": "object",
                      "required": [
                        "ok",
                        "verified",
                        "subjectId"
                      ],
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "enum": [
                            true
                          ]
                        },
                        "verified": {
                          "type": "boolean",
                          "enum": [
                            true
                          ]
                        },
                        "subjectId": {
                          "type": "string"
                        }
                      }
                    },
                    {
                      "type": "object",
                      "required": [
                        "ok",
                        "reason"
                      ],
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "enum": [
                            false
                          ]
                        },
                        "reason": {
                          "type": "string",
                          "enum": [
                            "invalid_request",
                            "purpose_mismatch",
                            "client_data_invalid",
                            "challenge_invalid",
                            "challenge_mismatch",
                            "origin_not_allowed",
                            "rp_id_mismatch",
                            "user_not_present",
                            "user_not_verified",
                            "attestation_invalid",
                            "attestation_signature_invalid",
                            "unsupported_algorithm",
                            "assertion_signature_invalid",
                            "sign_count_regression",
                            "subject_unverified",
                            "credential_exists",
                            "credential_unknown",
                            "storage_error",
                            "step_up_unconfigured",
                            "step_up_transport_error",
                            "step_up_provider_error",
                            "step_up_no_match",
                            "step_up_reference_required",
                            "aaguid_blocked",
                            "attestation_required",
                            "attestation_untrusted",
                            "aaguid_status_rejected",
                            "step_up_reference_replayed",
                            "step_up_claim_unavailable"
                          ]
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "ok": true,
                  "verified": true,
                  "subjectId": "subj_4821"
                }
              }
            }
          },
          "400": {
            "description": "`{\"ok\":false,\"reason\":\"invalid_request\"}` or `{\"ok\":false,\"reason\":\"purpose_mismatch\"}`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "reason"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "reason": {
                      "type": "string",
                      "enum": [
                        "invalid_request",
                        "purpose_mismatch",
                        "client_data_invalid",
                        "challenge_invalid",
                        "challenge_mismatch",
                        "origin_not_allowed",
                        "rp_id_mismatch",
                        "user_not_present",
                        "user_not_verified",
                        "attestation_invalid",
                        "attestation_signature_invalid",
                        "unsupported_algorithm",
                        "assertion_signature_invalid",
                        "sign_count_regression",
                        "subject_unverified",
                        "credential_exists",
                        "credential_unknown",
                        "storage_error",
                        "step_up_unconfigured",
                        "step_up_transport_error",
                        "step_up_provider_error",
                        "step_up_no_match",
                        "step_up_reference_required",
                        "aaguid_blocked",
                        "attestation_required",
                        "attestation_untrusted",
                        "aaguid_status_rejected",
                        "step_up_reference_replayed",
                        "step_up_claim_unavailable"
                      ]
                    }
                  }
                },
                "example": {
                  "ok": false,
                  "reason": "invalid_request"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/v1_InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/v1_ScopeForbidden"
          },
          "404": {
            "$ref": "#/components/responses/v1_GatedNotFound"
          },
          "429": {
            "$ref": "#/components/responses/v1_RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/handoff/mint": {
      "post": {
        "operationId": "postHandoffMint",
        "tags": [
          "Device Handoff"
        ],
        "summary": "Mint a browser-to-app handoff claim",
        "description": "Server-to-server (`sk_` key, scope `write:handoff`): the caller is your own backend, never a browser or a mobile device. Mints a session-bound, single-use claim that hands a verified browser session to a native app. It returns two independent 256-bit secrets, stored only as hashes: `exchangeCode`, the only value meant for the QR code or deep link, and `challenge`, a separate binding secret that you convey through your own out-of-band channel and never embed in the QR code. Both are required together at `POST /v1/handoff/consume`. Minting again for the same `sessionId` atomically supersedes any pending claim for that session, which supports cross-device rescans.\n\nNot enabled by default: when the capability is not enabled for your organisation both handoff endpoints answer the `GatedNotFound` 404.\n\n**Key scope availability.** At the time of writing the `write:handoff` scope is not among the scopes that can be selected when creating a server API key in the Backoffice, so a key created there cannot call the handoff endpoints.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "write:handoff"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "sessionId"
                ],
                "properties": {
                  "sessionId": {
                    "type": "string",
                    "maxLength": 256,
                    "description": "Opaque caller-generated correlation id; no PII."
                  }
                }
              },
              "example": {
                "sessionId": "01J8Z3K7QN6R2S4T6V8W0X2Y4Z"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The minted claim secrets and TTL.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "exchangeCode",
                    "challenge",
                    "sessionId",
                    "ttlSeconds",
                    "expiresAt"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "exchangeCode": {
                      "type": "string",
                      "description": "base64url(32 random bytes) — the ONLY secret meant for the QR/deep-link."
                    },
                    "challenge": {
                      "type": "string",
                      "description": "base64url(32 random bytes) — conveyed OUT-OF-BAND, never in the QR."
                    },
                    "sessionId": {
                      "type": "string"
                    },
                    "ttlSeconds": {
                      "type": "integer"
                    },
                    "expiresAt": {
                      "type": "integer",
                      "description": "Epoch milliseconds."
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "exchangeCode": "example-exchangeCode",
                  "challenge": "Y2hhbGxlbmdlLW5vbmNlLTAx",
                  "sessionId": "01J8Z3K7QN6R2S4T6V8W0X2Y4Z",
                  "ttlSeconds": 3600,
                  "expiresAt": 1768435200
                }
              }
            }
          },
          "400": {
            "description": "`Invalid or missing sessionId` or `Invalid body`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/v1_InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/v1_ScopeForbidden"
          },
          "404": {
            "$ref": "#/components/responses/v1_GatedNotFound"
          },
          "413": {
            "description": "`Payload too large` — over the 1024-byte cap.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/v1_RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/handoff/consume": {
      "post": {
        "operationId": "postHandoffConsume",
        "tags": [
          "Device Handoff"
        ],
        "summary": "Consume a browser-to-app handoff claim",
        "description": "Server-to-server (`sk_` key, scope `write:handoff`): called by your app's own backend when it resolves the deep link, never by the mobile device. The caller must present all of `sessionId`, `exchangeCode` and `challenge`. An exact match on every bound field, a pending status and an unexpired claim are all required, and the claim is consumed atomically, so an incorrect attempt never burns the real claim.\n\nEvery mismatch — a replay, another organisation, another session, a swapped challenge or an expired claim — gives the same closed `claim_invalid` rejection at a uniform HTTP 200, never a 4xx, because revealing which field failed would expose the claim's binding. Availability and the key-scope note are the same as for `POST /v1/handoff/mint`.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "write:handoff"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "sessionId",
                  "exchangeCode",
                  "challenge"
                ],
                "properties": {
                  "sessionId": {
                    "type": "string",
                    "maxLength": 256
                  },
                  "exchangeCode": {
                    "type": "string",
                    "maxLength": 512,
                    "description": "The `exchangeCode` scanned from the QR/deep-link."
                  },
                  "challenge": {
                    "type": "string",
                    "maxLength": 512,
                    "description": "The separately-conveyed binding secret."
                  }
                }
              },
              "example": {
                "sessionId": "01J8Z3K7QN6R2S4T6V8W0X2Y4Z",
                "exchangeCode": "example-exchangeCode",
                "challenge": "Y2hhbGxlbmdlLW5vbmNlLTAx"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The consume outcome — always HTTP 200 whether accepted or refused.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "type": "object",
                      "required": [
                        "ok",
                        "sessionId"
                      ],
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "enum": [
                            true
                          ]
                        },
                        "sessionId": {
                          "type": "string"
                        }
                      }
                    },
                    {
                      "type": "object",
                      "required": [
                        "ok",
                        "reason"
                      ],
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "enum": [
                            false
                          ]
                        },
                        "reason": {
                          "type": "string",
                          "enum": [
                            "claim_invalid"
                          ]
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "ok": true,
                  "sessionId": "01J8Z3K7QN6R2S4T6V8W0X2Y4Z"
                }
              }
            }
          },
          "400": {
            "description": "`Invalid or missing sessionId/exchangeCode/challenge` or `Invalid body`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/v1_InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/v1_ScopeForbidden"
          },
          "404": {
            "$ref": "#/components/responses/v1_GatedNotFound"
          },
          "413": {
            "description": "`Payload too large` — over the 2048-byte cap.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/v1_RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/device-delegation/create": {
      "post": {
        "operationId": "deviceDelegationCreate",
        "tags": [
          "Device Delegation"
        ],
        "summary": "Create a subject-scoped device delegation",
        "description": "Creates a delegation of device authority for a subject. The delegation is born `active`, subject to a cap on active delegations per subject (`device_delegation_limit_exceeded` when the cap is reached). The organisation is always the authenticated one: a tenant id in the body is never used and is omitted from the response. Every id field must match `^[a-zA-Z0-9._:-]{1,128}$`, except the server-generated delegation `id`, which is a UUID.\n\nNot enabled by default: when the device-registry capability is not enabled for your organisation the route answers the `GatedNotFound` 404. The three delegation operations share one rate-limit bucket per API key.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "write:identity"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "subjectId",
                  "delegatorId",
                  "delegateId"
                ],
                "properties": {
                  "subjectId": {
                    "type": "string",
                    "pattern": "^[a-zA-Z0-9._:-]{1,128}$",
                    "description": "The subject the delegation concerns (opaque, never raw PII)."
                  },
                  "delegatorId": {
                    "type": "string",
                    "pattern": "^[a-zA-Z0-9._:-]{1,128}$",
                    "description": "The principal granting the delegation."
                  },
                  "delegateId": {
                    "type": "string",
                    "pattern": "^[a-zA-Z0-9._:-]{1,128}$",
                    "description": "The device/principal receiving the delegation."
                  },
                  "scope": {
                    "type": "string",
                    "enum": [
                      "device_use",
                      "device_manage"
                    ],
                    "default": "device_use",
                    "description": "Defaults to `device_use` when omitted or not one of the closed values."
                  },
                  "evidenceRef": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "pattern": "^[a-zA-Z0-9._:-]{1,128}$",
                    "description": "Optional opaque id referencing the evidence/consent record justifying the delegation."
                  },
                  "expiresAt": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "format": "int64",
                    "description": "Optional epoch-ms timestamp. Omitted ⇒ no expiry. When present MUST be finite and strictly within `[now + 60000, now + 31536000000]` (a 1-minute floor, 1-year ceiling) — rejected, never clamped, outside that window."
                  },
                  "createdBy": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "pattern": "^[a-zA-Z0-9._:-]{1,128}$",
                    "description": "Optional opaque actor id for the audit trail."
                  }
                }
              },
              "example": {
                "subjectId": "subj_4821",
                "delegatorId": "dev_7a2b9c4d1e6f3a8b",
                "delegateId": "dev_2b9c4d1e6f3a8b7a",
                "scope": "device_use",
                "evidenceRef": "obj-front",
                "expiresAt": 1768435200,
                "createdBy": "tenant_42"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The minted delegation, born `active`. `tenantId` is omitted (the caller already knows its own tenant).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "delegation",
                    "requestId"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "delegation": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "subjectId": {
                          "type": "string"
                        },
                        "delegatorId": {
                          "type": "string"
                        },
                        "delegateId": {
                          "type": "string"
                        },
                        "scope": {
                          "type": "string",
                          "enum": [
                            "device_use",
                            "device_manage"
                          ]
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "active"
                          ]
                        },
                        "evidenceRef": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "expiresAt": {
                          "type": [
                            "integer",
                            "null"
                          ],
                          "format": "int64"
                        },
                        "revokedAt": {
                          "type": [
                            "integer",
                            "null"
                          ],
                          "format": "int64"
                        },
                        "createdBy": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "createdAt": {
                          "type": "integer",
                          "format": "int64"
                        },
                        "updatedAt": {
                          "type": "integer",
                          "format": "int64"
                        }
                      }
                    },
                    "requestId": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "delegation": {
                    "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                    "subjectId": "subj_4821",
                    "delegatorId": "dev_7a2b9c4d1e6f3a8b",
                    "delegateId": "dev_2b9c4d1e6f3a8b7a",
                    "scope": "device_use",
                    "status": "active",
                    "evidenceRef": "obj-front",
                    "expiresAt": 1768435200,
                    "revokedAt": 1,
                    "createdBy": "tenant_42",
                    "createdAt": 1,
                    "updatedAt": 1
                  },
                  "requestId": "req-test"
                }
              }
            }
          },
          "400": {
            "description": "`device_delegation_invalid_subject_id` / `_delegator_id` / `_delegate_id` / `_evidence_ref` / `_expiry` / `_created_by` / `_request` / `_limit_exceeded`, or a generic `invalid_request` for a malformed body.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/v1_InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/v1_ScopeForbidden"
          },
          "404": {
            "$ref": "#/components/responses/v1_GatedNotFound"
          },
          "413": {
            "$ref": "#/components/responses/v1_BodyTooLarge"
          },
          "415": {
            "description": "Non-JSON `Content-Type` (`invalid_request`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/v1_RateLimited"
          },
          "503": {
            "description": "`device_delegation_storage_unavailable` — a D1 write fault.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/device-delegation/list": {
      "post": {
        "operationId": "deviceDelegationList",
        "tags": [
          "Device Delegation"
        ],
        "summary": "List a subject's active device delegations",
        "description": "Lists the active, non-expired delegations of a subject. A subject with no active delegations, or an unknown subject, returns an empty array, never a distinguishing status (no existence oracle). Availability and rate-limit bucket are the same as for `POST /v1/device-delegation/create`; a `401` never consumes the bucket.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "write:identity"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "subjectId"
                ],
                "properties": {
                  "subjectId": {
                    "type": "string",
                    "description": "The subject whose active delegations to list."
                  }
                }
              },
              "example": {
                "subjectId": "subj_4821"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The subject's active, non-expired delegations (empty array if none / unknown subject).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "delegations",
                    "requestId"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "delegations": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "subjectId": {
                            "type": "string"
                          },
                          "delegatorId": {
                            "type": "string"
                          },
                          "delegateId": {
                            "type": "string"
                          },
                          "scope": {
                            "type": "string",
                            "enum": [
                              "device_use",
                              "device_manage"
                            ]
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "active"
                            ]
                          },
                          "evidenceRef": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "expiresAt": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "format": "int64"
                          },
                          "revokedAt": {
                            "type": [
                              "integer",
                              "null"
                            ],
                            "format": "int64"
                          },
                          "createdBy": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "createdAt": {
                            "type": "integer",
                            "format": "int64"
                          },
                          "updatedAt": {
                            "type": "integer",
                            "format": "int64"
                          }
                        }
                      }
                    },
                    "requestId": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "delegations": [
                    {
                      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                      "subjectId": "subj_4821",
                      "delegatorId": "dev_7a2b9c4d1e6f3a8b",
                      "delegateId": "dev_2b9c4d1e6f3a8b7a",
                      "scope": "device_use",
                      "status": "active",
                      "evidenceRef": "obj-front",
                      "expiresAt": 1768435200,
                      "revokedAt": 1,
                      "createdBy": "tenant_42",
                      "createdAt": 1,
                      "updatedAt": 1
                    }
                  ],
                  "requestId": "req-test"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request` — `subjectId` missing.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/v1_InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/v1_ScopeForbidden"
          },
          "404": {
            "$ref": "#/components/responses/v1_GatedNotFound"
          },
          "413": {
            "$ref": "#/components/responses/v1_BodyTooLarge"
          },
          "415": {
            "description": "Non-JSON `Content-Type` (`invalid_request`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/v1_RateLimited"
          },
          "503": {
            "description": "`device_delegation_storage_unavailable` — a D1 read fault.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/device-delegation/revoke": {
      "post": {
        "operationId": "deviceDelegationRevoke",
        "tags": [
          "Device Delegation"
        ],
        "summary": "Revoke a device delegation",
        "description": "Revokes a delegation. Revocation is terminal: a revoked delegation is never honoured again, and restoring access means creating a new delegation. A delegation id that belongs to another organisation answers `device_delegation_not_found`, byte-identical to an unknown id (no existence oracle). Availability and rate-limit bucket are the same as for `POST /v1/device-delegation/create`.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "write:identity"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "id"
                ],
                "properties": {
                  "id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "The delegation's own server-minted id (not the subject/delegator/delegate id)."
                  },
                  "revokedBy": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Optional opaque actor id for the audit trail; omitted ⇒ recorded as a SYSTEM actor."
                  }
                }
              },
              "example": {
                "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                "revokedBy": "example-revokedBy"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The delegation was revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "revoked",
                    "requestId"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "revoked": {
                      "type": "boolean"
                    },
                    "requestId": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "revoked": true,
                  "requestId": "req-test"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request` — `id` missing.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/v1_InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/v1_ScopeForbidden"
          },
          "404": {
            "description": "Either the capability is not enabled for your organisation (the `GatedNotFound` body), or the delegation `id` does not resolve for your organisation (`device_delegation_not_found`, byte-identical for an unknown id and an id of another organisation).",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/v1_ErrorEnvelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "V1 endpoint not found"
                          ]
                        },
                        "path": {
                          "type": "string"
                        },
                        "requestId": {
                          "type": "string"
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "413": {
            "$ref": "#/components/responses/v1_BodyTooLarge"
          },
          "415": {
            "description": "Non-JSON `Content-Type` (`invalid_request`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/v1_RateLimited"
          },
          "503": {
            "description": "`device_delegation_storage_unavailable` — a D1 write fault.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/recovery/cases": {
      "post": {
        "operationId": "recoveryOpenCase",
        "tags": [
          "Account Recovery"
        ],
        "summary": "Open a recovery case (currently always refused)",
        "description": "Self-service recovery case opening is not available today. A well-formed request never creates a case: the route validates the shape of `installId` (a UUID, then discarded — it is never treated as a subject reference) and answers the same closed business rejection with HTTP 200, which is the status the mobile backend contract inspects. A request that carries a `subjectId` of any type is rejected with `400 invalid_request`, so that no key holder can name a foreign subject.\n\nNot enabled by default: when the device-registry capability is not enabled for your organisation the route answers the `GatedNotFound` 404. The four `/v1/recovery/*` operations share one rate-limit bucket per API key.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "write:identity"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "installId",
                  "tier"
                ],
                "properties": {
                  "installId": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Validated for shape only (UUID v1-5) and discarded — never a subject reference."
                  },
                  "tier": {
                    "type": "string",
                    "enum": [
                      "fresh_reverification",
                      "trusted_referee",
                      "alternate_evidence",
                      "device_history_attestation",
                      "dual_control_override"
                    ]
                  },
                  "evidenceRef": {
                    "type": "string",
                    "pattern": "^[a-zA-Z0-9._:-]{1,128}$",
                    "description": "Optional opaque id."
                  },
                  "subjectId": {
                    "description": "NOT part of the frozen contract. Any own-property `subjectId` (of any type, including `null`) is rejected with `400 invalid_request` — never accepted-and-ignored."
                  }
                }
              },
              "example": {
                "installId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                "tier": "fresh_reverification",
                "evidenceRef": "obj-front",
                "subjectId": "subj_4821"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Always the closed business rejection today: no case is created.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "reason",
                    "requestId"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "reason": {
                      "type": "string",
                      "enum": [
                        "subject_resolution_required"
                      ]
                    },
                    "requestId": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "ok": false,
                  "reason": "subject_resolution_required",
                  "requestId": "req-test"
                }
              }
            }
          },
          "400": {
            "description": "Missing/invalid `installId` or `tier`, an invalid `evidenceRef` shape, or any own-property `subjectId` present.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/v1_InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/v1_ScopeForbidden"
          },
          "404": {
            "$ref": "#/components/responses/v1_GatedNotFound"
          },
          "413": {
            "$ref": "#/components/responses/v1_BodyTooLarge"
          },
          "415": {
            "description": "Non-JSON `Content-Type` (`invalid_request`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/v1_RateLimited"
          },
          "503": {
            "description": "`registry_write_failed` — unexpected handler error (never a raw exception).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "reason": {
                      "type": "string",
                      "enum": [
                        "registry_write_failed"
                      ]
                    },
                    "requestId": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "ok": false,
                  "reason": "registry_write_failed",
                  "requestId": "req-test"
                }
              }
            }
          }
        },
        "x-noxtica-status": "partial"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/recovery/cases/{caseId}": {
      "get": {
        "operationId": "recoveryGetCase",
        "tags": [
          "Account Recovery"
        ],
        "summary": "Read a recovery case's status",
        "description": "Polls the status of a recovery case. The stored case is redacted before it is returned: `subjectId`, `evidenceRef`, `refereeId`, `fraudReviewVerdict`, `createdBy` and `resolutionReasonCode` are never part of the response. A `caseId` that belongs to another organisation answers the same `404` as an unknown id (no existence oracle). Availability and rate-limit bucket are the same as for `POST /v1/recovery/cases`.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "write:identity"
            ]
          }
        ],
        "parameters": [
          {
            "name": "caseId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-zA-Z0-9._:-]{1,128}$"
            },
            "description": "Opaque case id, decoded by the router and re-validated inside the handler."
          }
        ],
        "responses": {
          "200": {
            "description": "The redacted case projection.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "case",
                    "requestId"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "case": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "tenantId": {
                          "type": "string"
                        },
                        "tier": {
                          "type": "string",
                          "enum": [
                            "fresh_reverification",
                            "trusted_referee",
                            "alternate_evidence",
                            "device_history_attestation",
                            "dual_control_override"
                          ]
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "opened",
                            "pending_referee",
                            "pending_dual_control",
                            "pending_fraud_review",
                            "approved",
                            "denied",
                            "blocked_external",
                            "expired"
                          ]
                        },
                        "resultingVerificationLevel": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "resultingStatus": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "enum": [
                            "active",
                            "active_limited",
                            "proof_restored"
                          ]
                        },
                        "slaDueAt": {
                          "type": "integer",
                          "format": "int64"
                        },
                        "resolvedAt": {
                          "type": [
                            "integer",
                            "null"
                          ],
                          "format": "int64"
                        },
                        "createdAt": {
                          "type": "integer",
                          "format": "int64"
                        },
                        "updatedAt": {
                          "type": "integer",
                          "format": "int64"
                        }
                      }
                    },
                    "requestId": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "case": {
                    "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                    "tenantId": "tenant_42",
                    "tier": "fresh_reverification",
                    "status": "opened",
                    "resultingVerificationLevel": "example-resultingVerificationLevel",
                    "resultingStatus": "active",
                    "slaDueAt": 1,
                    "resolvedAt": 1,
                    "createdAt": 1,
                    "updatedAt": 1
                  },
                  "requestId": "req-test"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request` (opaque-id shape violation), or `Invalid caseId` (router-level `decodeURIComponent` throw on malformed percent-encoding).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/v1_InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/v1_ScopeForbidden"
          },
          "404": {
            "description": "Either the capability is not enabled for your organisation (the `GatedNotFound` body), or `recovery_case_not_found`: the `caseId` is well formed but no case exists for your organisation (a case of another organisation resolves identically).",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "V1 endpoint not found"
                          ]
                        },
                        "path": {
                          "type": "string"
                        },
                        "requestId": {
                          "type": "string"
                        }
                      }
                    },
                    {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "enum": [
                            false
                          ]
                        },
                        "reason": {
                          "type": "string",
                          "enum": [
                            "recovery_case_not_found"
                          ]
                        },
                        "requestId": {
                          "type": "string"
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "error": "V1 endpoint not found",
                  "path": "/v1/kyc/verify",
                  "requestId": "req-test"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/v1_RateLimited"
          },
          "503": {
            "description": "`registry_write_failed` — unexpected handler error.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "reason": {
                      "type": "string",
                      "enum": [
                        "registry_write_failed"
                      ]
                    },
                    "requestId": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "ok": false,
                  "reason": "registry_write_failed",
                  "requestId": "req-test"
                }
              }
            }
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/recovery/appeals": {
      "post": {
        "operationId": "recoveryOpenAppeal",
        "tags": [
          "Account Recovery"
        ],
        "summary": "Open an appeal (currently always refused)",
        "description": "Opening an appeal is not available today. Because no case can be opened, the route refuses unconditionally with the same closed reason as `POST /v1/recovery/cases`, and it does not read or validate the request body: any body, or none, produces the identical response. Availability and rate-limit bucket are the same as for the other recovery routes.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "write:identity"
            ]
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "caseId": {
                    "type": "string",
                    "description": "Nominal frozen-BFF-contract field. Never read or validated by this handler."
                  }
                }
              },
              "example": {
                "caseId": "example-caseId"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Always the closed business rejection today: no appeal is created.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "reason",
                    "requestId"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "reason": {
                      "type": "string",
                      "enum": [
                        "subject_resolution_required"
                      ]
                    },
                    "requestId": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "ok": false,
                  "reason": "subject_resolution_required",
                  "requestId": "req-test"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/v1_InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/v1_ScopeForbidden"
          },
          "404": {
            "$ref": "#/components/responses/v1_GatedNotFound"
          },
          "429": {
            "$ref": "#/components/responses/v1_RateLimited"
          },
          "503": {
            "description": "`registry_write_failed` — unexpected handler error.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "reason": {
                      "type": "string",
                      "enum": [
                        "registry_write_failed"
                      ]
                    },
                    "requestId": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "ok": false,
                  "reason": "registry_write_failed",
                  "requestId": "req-test"
                }
              }
            }
          }
        },
        "x-noxtica-status": "partial"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/recovery/appeals/{appealId}": {
      "get": {
        "operationId": "recoveryGetAppeal",
        "tags": [
          "Account Recovery"
        ],
        "summary": "Read an appeal's status",
        "description": "Polls the status of an appeal. Unlike a case, no field of an appeal is redacted. A missing appeal reuses the case reason `recovery_case_not_found`; there is no separate appeal-not-found code. Availability and rate-limit bucket are the same as for the other recovery routes.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "write:identity"
            ]
          }
        ],
        "parameters": [
          {
            "name": "appealId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[a-zA-Z0-9._:-]{1,128}$"
            },
            "description": "Opaque appeal id, decoded by the router and re-validated inside the handler."
          }
        ],
        "responses": {
          "200": {
            "description": "The full (unredacted) appeal projection.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "appeal",
                    "requestId"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "appeal": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "tenantId": {
                          "type": "string"
                        },
                        "caseId": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "openedAt": {
                          "type": "integer",
                          "format": "int64"
                        },
                        "slaDueAt": {
                          "type": "integer",
                          "format": "int64"
                        },
                        "resolvedAt": {
                          "type": [
                            "integer",
                            "null"
                          ],
                          "format": "int64"
                        },
                        "outcome": {
                          "type": "string",
                          "enum": [
                            "pending",
                            "upheld",
                            "overturned",
                            "expired"
                          ]
                        },
                        "resolvedBy": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "createdAt": {
                          "type": "integer",
                          "format": "int64"
                        },
                        "updatedAt": {
                          "type": "integer",
                          "format": "int64"
                        }
                      }
                    },
                    "requestId": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "appeal": {
                    "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                    "tenantId": "tenant_42",
                    "caseId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                    "openedAt": 1,
                    "slaDueAt": 1,
                    "resolvedAt": 1,
                    "outcome": "pending",
                    "resolvedBy": "example-resolvedBy",
                    "createdAt": 1,
                    "updatedAt": 1
                  },
                  "requestId": "req-test"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request` (opaque-id shape violation), or `Invalid appealId` (router-level `decodeURIComponent` throw).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/v1_InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/v1_ScopeForbidden"
          },
          "404": {
            "description": "Either the capability is not enabled for your organisation (the `GatedNotFound` body), or `recovery_case_not_found`: no appeal with that id exists for your organisation.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "error": {
                          "type": "string",
                          "enum": [
                            "V1 endpoint not found"
                          ]
                        },
                        "path": {
                          "type": "string"
                        },
                        "requestId": {
                          "type": "string"
                        }
                      }
                    },
                    {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "enum": [
                            false
                          ]
                        },
                        "reason": {
                          "type": "string",
                          "enum": [
                            "recovery_case_not_found"
                          ]
                        },
                        "requestId": {
                          "type": "string"
                        }
                      }
                    }
                  ]
                },
                "example": {
                  "error": "V1 endpoint not found",
                  "path": "/v1/kyc/verify",
                  "requestId": "req-test"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/v1_RateLimited"
          },
          "503": {
            "description": "`registry_write_failed` — unexpected handler error.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "reason": {
                      "type": "string",
                      "enum": [
                        "registry_write_failed"
                      ]
                    },
                    "requestId": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "ok": false,
                  "reason": "registry_write_failed",
                  "requestId": "req-test"
                }
              }
            }
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/wallet/status": {
      "post": {
        "operationId": "walletStatus",
        "tags": [
          "Wallet Status"
        ],
        "summary": "Read a subject's device status and verification level",
        "description": "Read-only, organisation-scoped device status and `verificationLevel` for a subject. It is built on the same trust decision that `POST /v1/kyc/reverify` reads, plus relying-party log, consent-receipt and pairwise-pseudonym transparency reads, each independently fail-closed. This is the identity and device wallet, not a payment wallet.\n\n`verificationLevel` is present only on a trusted decision, never on a proof-only link; `proofOnly: true` marks a proof-only partition (status `proofed_unbound`, level `null`). `stepUpRequired` is reported, never enforced here, only when the decision demands it. An unexpected internal fault answers `200` with every field null (fail-closed: never a 5xx, never a positive status).\n\nNot enabled by default: when the device-registry capability is not enabled for your organisation the route answers the `GatedNotFound` 404.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "write:identity"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "subjectId"
                ],
                "properties": {
                  "subjectId": {
                    "type": "string",
                    "description": "The opaque FR-8 pseudonym identifying the device/subject."
                  }
                }
              },
              "example": {
                "subjectId": "subj_4821"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The readout — ALWAYS 200, including on internal fault (every field nulled in that case; never a happy-path 5xx).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "verificationLevel",
                    "status",
                    "pairwisePseudonym",
                    "consent",
                    "rpLog",
                    "requestId"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "verificationLevel": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Present only on a trusted decision."
                    },
                    "status": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "pairwisePseudonym": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "consent": {
                      "type": [
                        "object",
                        "null"
                      ],
                      "properties": {
                        "version": {
                          "type": "string"
                        },
                        "grantedAt": {
                          "type": "string"
                        },
                        "revoked": {
                          "type": "boolean"
                        }
                      }
                    },
                    "rpLog": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "event": {
                            "type": "string"
                          },
                          "at": {
                            "type": "string"
                          }
                        }
                      }
                    },
                    "proofOnly": {
                      "type": "boolean",
                      "description": "Present (true) only for the proof-only partition."
                    },
                    "stepUpRequired": {
                      "type": "boolean",
                      "description": "Present (true) only when the authoritative decision demands step-up."
                    },
                    "requestId": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "verificationLevel": "verified",
                  "status": "example-status",
                  "pairwisePseudonym": "example-pairwisePseudonym",
                  "consent": {
                    "version": "example-version",
                    "grantedAt": "example-grantedAt",
                    "revoked": true
                  },
                  "rpLog": [
                    {
                      "event": "example-event",
                      "at": "example-at"
                    }
                  ],
                  "proofOnly": true,
                  "stepUpRequired": true,
                  "requestId": "req-test"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request` — malformed body or missing `subjectId`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/v1_InvalidApiKey"
          },
          "403": {
            "$ref": "#/components/responses/v1_ScopeForbidden"
          },
          "404": {
            "$ref": "#/components/responses/v1_GatedNotFound"
          },
          "413": {
            "$ref": "#/components/responses/v1_BodyTooLarge"
          },
          "429": {
            "$ref": "#/components/responses/v1_RateLimited"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/wallet/suspend": {
      "post": {
        "operationId": "walletSuspend",
        "tags": [
          "Wallet Status"
        ],
        "summary": "Suspend a subject's device-bound wallet state",
        "description": "Executes the `suspended` transition for a subject's device-bound wallet state. Name the subject in one of two ways: `attestationId` (preferred, and it takes precedence when both are present), resolved server-side from a fresh single-use device-attestation claim; or `subjectId` (a trusted-caller fallback), which additionally requires the `write:identity:trusted-subject` scope and otherwise answers a genuine `403`.\n\nEvery refusal collapses to a closed result so that no response reveals whether a subject exists: an attestation that cannot be resolved gives `status: \"subject_not_attested\"`, and any illegal transition or internal fault gives `status: \"suspend_failed\"`. The route always answers `200`, with `suspended: true` on a legal transition. It shares the write-family rate-limit bucket of `POST /v1/kyc/verify`. Availability is the same as for `POST /v1/wallet/status`.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "write:identity"
            ]
          },
          {
            "v1_ApiKeyAuth": [
              "write:identity",
              "write:identity:trusted-subject"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "description": "EXACTLY one of `attestationId` or `subjectId` must be present (both may be sent; `attestationId` takes precedence and `subjectId` is then silently ignored).",
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "attestationId": {
                    "type": "string",
                    "description": "Preferred. A fresh device-attestation reference the collector resolves to a subject server-side; consumed single-use."
                  },
                  "subjectId": {
                    "type": "string",
                    "description": "Trusted-caller fallback. Requires the additive `write:identity:trusted-subject` scope; the caller already knows the subject it names."
                  }
                }
              },
              "example": {
                "attestationId": "att_9c6b2f7e4a3d4c8e9f1a2b3c4d5e6f70",
                "subjectId": "subj_4821"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "ALWAYS 200. `suspended:true` on a legal transition; `suspended:false` with `status:'subject_not_attested'` on an attestation-resolution miss; `suspended:false` with `status:'suspend_failed'` on any illegal-transition reason or an internal fault.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "suspended",
                    "status",
                    "requestId"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "suspended": {
                      "type": "boolean"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "suspended",
                        "subject_not_attested",
                        "suspend_failed"
                      ]
                    },
                    "requestId": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "suspended": true,
                  "status": "suspended",
                  "requestId": "req-test"
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request` — malformed body, or neither `subjectId` nor `attestationId` present.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/v1_InvalidApiKey"
          },
          "403": {
            "description": "The `subjectId` fallback was used WITHOUT the additive `write:identity:trusted-subject` scope (the base `write:identity`-scope-missing case uses the standard `ScopeForbidden` shape).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string",
                      "example": "API key does not have write:identity:trusted-subject scope"
                    },
                    "requestId": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "error": "API key does not have write:identity:trusted-subject scope",
                  "requestId": "req-test"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/v1_GatedNotFound"
          },
          "413": {
            "$ref": "#/components/responses/v1_BodyTooLarge"
          },
          "429": {
            "$ref": "#/components/responses/v1_RateLimited"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/offline/nonce-pool": {
      "post": {
        "operationId": "offlineNoncePoolMint",
        "tags": [
          "Offline Capture"
        ],
        "summary": "Mint a batch of offline-capture nonces",
        "description": "Mints 1 to 5 (default 1) single-use, time-limited nonces while the caller has connectivity, for later redemption at `POST /v1/offline/capture-bundle`. This is a resumable-upload scope, not a truly offline start: the client must be online when it mints. Each nonce is stored only as a keyed digest and the raw nonce is returned exactly once. The default lifetime is 72 hours.\n\nA caller classified as first-party capture on its API key must hold an active legal-basis receipt to mint; otherwise it is refused with `403 kyc_legal_basis_receipt_required`. Ordinary tenant traffic is unaffected. Not enabled by default: when the capability is not enabled for your organisation the route answers the `GatedNotFound` 404.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "write:identity"
            ]
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "count": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 5,
                    "default": 1,
                    "description": "Non-integer or out-of-range values fall back to the default (1) rather than erroring."
                  }
                }
              },
              "example": {
                "count": 1
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The minted nonce pool. Raw nonces are visible exactly once.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "nonces",
                    "requestId"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "nonces": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "nonce": {
                            "type": "string"
                          },
                          "expiresAt": {
                            "type": "integer",
                            "format": "int64"
                          }
                        }
                      }
                    },
                    "requestId": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "nonces": [
                    {
                      "nonce": "nonce_5f3a8c1e2d4b6f709182a3b4c5d6e7f8",
                      "expiresAt": 1768435200
                    }
                  ],
                  "requestId": "req-test"
                }
              }
            }
          },
          "400": {
            "description": "Malformed body, bad `Content-Length`, or a non-JSON-object body (`invalid_request`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/v1_InvalidApiKey"
          },
          "403": {
            "description": "`kyc_legal_basis_receipt_required` (legal-basis gate refusal), OR the standard scope-forbidden shape.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/v1_GatedNotFound"
          },
          "413": {
            "$ref": "#/components/responses/v1_BodyTooLarge"
          },
          "415": {
            "description": "Non-JSON `Content-Type` (`invalid_request`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/v1_RateLimited"
          },
          "503": {
            "description": "`offline_capture_storage_unavailable` (digest secret unset / mint fault), or `kyc_first_party_provenance_unavailable` (legal-basis gate fault).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/offline/capture-bundle": {
      "post": {
        "operationId": "offlineCaptureBundleAdmit",
        "tags": [
          "Offline Capture"
        ],
        "summary": "Admit a deferred-upload offline capture bundle",
        "description": "Redeems a nonce minted by `POST /v1/offline/nonce-pool` to admit an on-device-encrypted, time-limited capture bundle for deferred upload. This endpoint never sees the bundle's encryption key or media, only control-plane admission fields. It is capture-only: a body that carries any verdict- or attestation-shaped key (`verdict`, `verified`, `attestationId`, `reasonCodes` and similar) is rejected before any nonce lookup or write, because attestation stays online-only.\n\nThe call is idempotent on the `Idempotency-Key` header: a replay with an identical body returns the same stored response byte for byte, even long after the nonce's lifetime has elapsed, and a replay with a different body under the same key is a `409` conflict. The request body is limited to 1 MiB. Availability and the legal-basis rule are the same as for `POST /v1/offline/nonce-pool`.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "write:identity"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKeyRequired"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "bundleId",
                  "nonce",
                  "capturedAt"
                ],
                "properties": {
                  "bundleId": {
                    "type": "string",
                    "maxLength": 256,
                    "description": "Caller-assigned bundle identifier (accepted as `bundleId` or `bundle_id`)."
                  },
                  "nonce": {
                    "type": "string",
                    "description": "A nonce previously minted by `POST /v1/offline/nonce-pool`."
                  },
                  "capturedAt": {
                    "type": "integer",
                    "format": "int64",
                    "minimum": 0,
                    "description": "Epoch-millisecond capture timestamp (accepted as `capturedAt` or `captured_at`); must be a finite, non-negative safe integer."
                  }
                }
              },
              "example": {
                "bundleId": "example-bundleId",
                "nonce": "nonce_5f3a8c1e2d4b6f709182a3b4c5d6e7f8",
                "capturedAt": 0
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "The bundle admission was accepted (fresh claim or a byte-identical idempotent replay).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "ok",
                    "bundleId",
                    "status",
                    "capturedAt"
                  ],
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "bundleId": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "accepted"
                      ]
                    },
                    "capturedAt": {
                      "type": "integer",
                      "format": "int64"
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "bundleId": "example-bundleId",
                  "status": "accepted",
                  "capturedAt": 1
                }
              }
            }
          },
          "400": {
            "description": "`invalid_request` (missing/invalid `Idempotency-Key` or required fields, malformed body), `offline_capture_verdict_claim_rejected` (verdict-shaped key present), or `offline_capture_nonce_invalid` (unknown nonce).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/v1_InvalidApiKey"
          },
          "403": {
            "description": "`kyc_legal_basis_receipt_required`, or the standard scope-forbidden shape.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/v1_GatedNotFound"
          },
          "409": {
            "description": "`offline_capture_idempotency_conflict` (same key, differing body), or `offline_capture_nonce_replayed` (nonce already claimed by a different bundle).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "410": {
            "description": "`offline_capture_bundle_expired` — the nonce is past its TTL; the nonce row is deleted and the bundle is never processed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "413": {
            "description": "Body exceeds 1 MiB (`body_too_large`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "415": {
            "description": "Non-JSON `Content-Type` (`invalid_request`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/v1_RateLimited"
          },
          "503": {
            "description": "`offline_capture_storage_unavailable` (digest secret unset, or a storage/admission fault), or `kyc_first_party_provenance_unavailable` (legal-basis gate fault, or a ref-stamp fault after a fresh claim — the claimed row is then deleted).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/v1_ErrorEnvelope"
                },
                "example": {
                  "error": "invalid_request",
                  "requestId": "req-test"
                }
              }
            }
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/apm/projects": {
      "get": {
        "operationId": "v1ApmListProjects",
        "tags": [
          "APM Observability"
        ],
        "summary": "List APM projects",
        "description": "Lists tenant-owned observability projects from PostgreSQL authority. Results are cursor-paginated and never cached.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "read:apm"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ApmListLimit"
          },
          {
            "$ref": "#/components/parameters/ApmCursor"
          }
        ],
        "responses": {
          "200": {
            "description": "Project page.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApmProjectList"
                },
                "example": {
                  "ok": true,
                  "items": [
                    {
                      "project_id": "checkout",
                      "display_name": "Checkout",
                      "state": "active",
                      "region_id": "us-central1",
                      "data_plane_id": "primary",
                      "capture_enabled": false,
                      "enabled_signals": [
                        "traces"
                      ],
                      "authority_epoch": 7,
                      "erasure_epoch": 2,
                      "created_at": "2026-08-01T00:00:00.000Z",
                      "updated_at": "2026-09-01T00:00:00.000Z"
                    }
                  ],
                  "count": 1,
                  "truncated": false,
                  "next_cursor": null,
                  "freshness": "postgres_authority",
                  "completeness": "complete"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ApmInvalid"
          },
          "401": {
            "$ref": "#/components/responses/ApmUnauthorized"
          },
          "403": {
            "$ref": "#/components/responses/ApmForbidden"
          },
          "429": {
            "$ref": "#/components/responses/ApmRateLimited"
          },
          "503": {
            "$ref": "#/components/responses/ApmControlUnavailable"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/apm/projects/{projectId}/environments": {
      "get": {
        "operationId": "v1ApmListProjectEnvironments",
        "tags": [
          "APM Observability"
        ],
        "summary": "List project environments",
        "description": "Lists environments belonging to one tenant-owned APM project from PostgreSQL authority.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "read:apm"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ApmProjectIdPath"
          },
          {
            "$ref": "#/components/parameters/ApmListLimit"
          },
          {
            "$ref": "#/components/parameters/ApmCursor"
          }
        ],
        "responses": {
          "200": {
            "description": "Environment page.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApmEnvironmentList"
                },
                "example": {
                  "ok": true,
                  "project_id": "checkout",
                  "items": [
                    {
                      "project_id": "checkout",
                      "environment_id": "prod",
                      "display_name": "Production",
                      "environment_kind": "production",
                      "state": "active",
                      "region_id": "us-central1",
                      "data_plane_id": "primary",
                      "capture_enabled": false,
                      "allowed_signals": [
                        "traces"
                      ],
                      "sampling_policy_id": "baseline",
                      "retention_policy_version": 3,
                      "privacy_policy_version": 2,
                      "authority_epoch": 7,
                      "erasure_epoch": 2,
                      "quota_manifest_revision": 4,
                      "parser_manifest_revision": 5,
                      "created_at": "2026-08-01T00:00:00.000Z",
                      "updated_at": "2026-09-01T00:00:00.000Z"
                    }
                  ],
                  "count": 1,
                  "truncated": false,
                  "next_cursor": null,
                  "freshness": "postgres_authority",
                  "completeness": "complete"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ApmInvalid"
          },
          "401": {
            "$ref": "#/components/responses/ApmUnauthorized"
          },
          "403": {
            "$ref": "#/components/responses/ApmForbidden"
          },
          "404": {
            "$ref": "#/components/responses/ApmNotFound"
          },
          "429": {
            "$ref": "#/components/responses/ApmRateLimited"
          },
          "503": {
            "$ref": "#/components/responses/ApmControlUnavailable"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/apm/projects/{projectId}/environments/{environmentId}/policy": {
      "get": {
        "operationId": "v1ApmGetEnvironmentPolicy",
        "tags": [
          "APM Observability"
        ],
        "summary": "Read an environment policy",
        "description": "Returns the authoritative environment policy plus bounded sampling and retention policy inventories.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "read:apm"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ApmProjectIdPath"
          },
          {
            "$ref": "#/components/parameters/ApmEnvironmentIdPath"
          }
        ],
        "responses": {
          "200": {
            "description": "Policy snapshot.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApmPolicySnapshot"
                },
                "example": {
                  "ok": true,
                  "project_id": "checkout",
                  "environment_id": "prod",
                  "policy": {
                    "project_id": "checkout",
                    "environment_id": "prod",
                    "display_name": "Production",
                    "environment_kind": "production",
                    "state": "active",
                    "region_id": "us-central1",
                    "data_plane_id": "primary",
                    "capture_enabled": false,
                    "allowed_signals": [
                      "traces"
                    ],
                    "sampling_policy_id": "baseline",
                    "retention_policy_version": 3,
                    "privacy_policy_version": 2,
                    "authority_epoch": 7,
                    "erasure_epoch": 2,
                    "quota_manifest_revision": 4,
                    "parser_manifest_revision": 5,
                    "created_at": "2026-08-01T00:00:00.000Z",
                    "updated_at": "2026-09-01T00:00:00.000Z"
                  },
                  "sampling_policies": [],
                  "sampling_policy_count": 0,
                  "sampling_policies_truncated": false,
                  "retention_policies": [],
                  "retention_policy_count": 0,
                  "retention_policies_truncated": false,
                  "freshness": {
                    "source": "postgres_authority",
                    "updated_at": "2026-09-01T00:00:00.000Z"
                  },
                  "completeness": {
                    "sampling_policies": "complete",
                    "retention_policies": "complete"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ApmInvalid"
          },
          "401": {
            "$ref": "#/components/responses/ApmUnauthorized"
          },
          "403": {
            "$ref": "#/components/responses/ApmForbidden"
          },
          "404": {
            "$ref": "#/components/responses/ApmNotFound"
          },
          "429": {
            "$ref": "#/components/responses/ApmRateLimited"
          },
          "503": {
            "$ref": "#/components/responses/ApmControlUnavailable"
          }
        },
        "x-noxtica-status": "available"
      },
      "put": {
        "operationId": "v1ApmUpdateEnvironmentPolicy",
        "tags": [
          "APM Observability"
        ],
        "summary": "Update an environment policy",
        "description": "Updates a closed allowlist using optimistic authority-epoch concurrency. While capture rollout is OFF, `capture_enabled: true` is unavailable and returns 409 `capture_unavailable`; clients may only leave it absent or set it false.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "write:apm"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ApmProjectIdPath"
          },
          {
            "$ref": "#/components/parameters/ApmEnvironmentIdPath"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ApmPolicyUpdate"
              },
              "example": {
                "expected_authority_epoch": 7,
                "capture_enabled": false,
                "allowed_signals": [
                  "traces"
                ],
                "sampling_policy_id": "baseline"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated authoritative policy.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApmPolicyUpdateResult"
                },
                "example": {
                  "ok": true,
                  "project_id": "checkout",
                  "environment_id": "prod",
                  "policy": {
                    "project_id": "checkout",
                    "environment_id": "prod",
                    "display_name": "Production",
                    "environment_kind": "production",
                    "state": "active",
                    "region_id": "us-central1",
                    "data_plane_id": "primary",
                    "capture_enabled": false,
                    "allowed_signals": [
                      "traces"
                    ],
                    "sampling_policy_id": "baseline",
                    "retention_policy_version": 3,
                    "privacy_policy_version": 2,
                    "authority_epoch": 8,
                    "erasure_epoch": 2,
                    "quota_manifest_revision": 4,
                    "parser_manifest_revision": 5,
                    "created_at": "2026-08-01T00:00:00.000Z",
                    "updated_at": "2026-09-21T00:00:00.000Z"
                  },
                  "count": 1,
                  "truncated": false,
                  "freshness": {
                    "source": "postgres_authority",
                    "updated_at": "2026-09-21T00:00:00.000Z"
                  },
                  "completeness": "complete"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ApmInvalid"
          },
          "401": {
            "$ref": "#/components/responses/ApmUnauthorized"
          },
          "403": {
            "$ref": "#/components/responses/ApmForbidden"
          },
          "404": {
            "$ref": "#/components/responses/ApmNotFound"
          },
          "409": {
            "description": "Capture is unavailable or the expected authority epoch is stale.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApmConflict"
                },
                "example": {
                  "ok": false,
                  "error": "capture_unavailable",
                  "available": false,
                  "reason": "capture_rollout_disabled",
                  "requestId": "req-test"
                }
              }
            }
          },
          "503": {
            "$ref": "#/components/responses/ApmControlUnavailable"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/apm/traces": {
      "get": {
        "operationId": "v1ApmSearchTraces",
        "tags": [
          "APM Observability"
        ],
        "summary": "Search traces",
        "description": "Searches the warehouse within one explicit project/environment and a range no longer than 31 days. Rows expose only the query allowlist; completeness and freshness are not inferred.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "read:apm"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ApmProjectIdQuery"
          },
          {
            "$ref": "#/components/parameters/ApmEnvironmentIdQuery"
          },
          {
            "$ref": "#/components/parameters/ApmFrom"
          },
          {
            "$ref": "#/components/parameters/ApmTo"
          },
          {
            "$ref": "#/components/parameters/ApmQueryLimit"
          },
          {
            "$ref": "#/components/parameters/ApmCursor"
          },
          {
            "name": "service_name",
            "in": "query",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 256,
              "pattern": "^[A-Za-z0-9._:/-]+$"
            }
          },
          {
            "name": "release_id",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/ApmScopedId"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "ok",
                "error"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Trace summary page.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApmTraceSearchResult"
                },
                "example": {
                  "ok": true,
                  "available": true,
                  "project_id": "checkout",
                  "environment_id": "prod",
                  "items": [
                    {
                      "traceId": "0123456789abcdef0123456789abcdef",
                      "startTime": "2026-09-20T12:00:00.000Z",
                      "partial": false,
                      "completeness": "complete",
                      "freshnessWatermark": "2026-09-20T12:01:00.000Z",
                      "ingestedAt": "2026-09-20T12:01:01.000Z"
                    }
                  ],
                  "count": 1,
                  "truncated": false,
                  "next_cursor": null,
                  "partial": false,
                  "completeness": "complete",
                  "freshness": {
                    "watermark": "2026-09-20T12:01:00.000Z",
                    "ingested_at": "2026-09-20T12:01:01.000Z"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ApmInvalid"
          },
          "401": {
            "$ref": "#/components/responses/ApmUnauthorized"
          },
          "403": {
            "$ref": "#/components/responses/ApmForbidden"
          },
          "404": {
            "$ref": "#/components/responses/ApmNotFound"
          },
          "429": {
            "$ref": "#/components/responses/ApmRateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ApmInternal"
          },
          "503": {
            "$ref": "#/components/responses/ApmWarehouseUnavailable"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/apm/traces/{traceId}": {
      "get": {
        "operationId": "v1ApmGetTrace",
        "tags": [
          "APM Observability"
        ],
        "summary": "Read trace detail",
        "description": "Returns a trace summary and a bounded timeline. Parent-edge completeness is explicitly false in this launch contract.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "read:apm"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ApmTraceIdPath"
          },
          {
            "$ref": "#/components/parameters/ApmProjectIdQuery"
          },
          {
            "$ref": "#/components/parameters/ApmEnvironmentIdQuery"
          },
          {
            "$ref": "#/components/parameters/ApmFrom"
          },
          {
            "$ref": "#/components/parameters/ApmTo"
          },
          {
            "$ref": "#/components/parameters/ApmQueryLimit"
          }
        ],
        "responses": {
          "200": {
            "description": "Trace detail and timeline.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApmTraceDetailResult"
                },
                "example": {
                  "ok": true,
                  "available": true,
                  "project_id": "checkout",
                  "environment_id": "prod",
                  "summary": {
                    "traceId": "0123456789abcdef0123456789abcdef",
                    "startTime": "2026-09-20T12:00:00.000Z",
                    "partial": false,
                    "completeness": "complete",
                    "freshnessWatermark": "2026-09-20T12:01:00.000Z",
                    "ingestedAt": "2026-09-20T12:01:01.000Z"
                  },
                  "timeline": [
                    {
                      "traceId": "0123456789abcdef0123456789abcdef",
                      "spanId": "aaaaaaaaaaaaaaaa",
                      "parentSpanId": "bbbbbbbbbbbbbbbb",
                      "completeness": "partial",
                      "ingestedAt": "2026-09-20T12:01:01.000Z"
                    }
                  ],
                  "count": 1,
                  "truncated": false,
                  "partial": true,
                  "completeness": {
                    "summary": "complete",
                    "timeline": "partial"
                  },
                  "freshness": {
                    "watermark": "2026-09-20T12:01:00.000Z",
                    "ingested_at": "2026-09-20T12:01:01.000Z"
                  },
                  "parent_edges_complete": false
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ApmInvalid"
          },
          "401": {
            "$ref": "#/components/responses/ApmUnauthorized"
          },
          "403": {
            "$ref": "#/components/responses/ApmForbidden"
          },
          "404": {
            "$ref": "#/components/responses/ApmNotFound"
          },
          "429": {
            "$ref": "#/components/responses/ApmRateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ApmInternal"
          },
          "503": {
            "$ref": "#/components/responses/ApmWarehouseUnavailable"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/apm/services": {
      "get": {
        "operationId": "v1ApmListServices",
        "tags": [
          "APM Observability"
        ],
        "summary": "List service health",
        "description": "Returns bounded aggregate health rows for one project/environment and a range no longer than 31 days.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "read:apm"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ApmProjectIdQuery"
          },
          {
            "$ref": "#/components/parameters/ApmEnvironmentIdQuery"
          },
          {
            "$ref": "#/components/parameters/ApmFrom"
          },
          {
            "$ref": "#/components/parameters/ApmTo"
          },
          {
            "$ref": "#/components/parameters/ApmQueryLimit"
          }
        ],
        "responses": {
          "200": {
            "description": "Service health page.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApmServiceListResult"
                },
                "example": {
                  "ok": true,
                  "available": true,
                  "project_id": "checkout",
                  "environment_id": "prod",
                  "items": [
                    {
                      "service_name": "checkout-api",
                      "trace_count": 120,
                      "error_trace_count": 3,
                      "error_rate": 0.025,
                      "p50_duration_ms": 42,
                      "p95_duration_ms": 310,
                      "completeness": "unknown",
                      "freshness_watermark": "2026-09-20T12:01:00.000Z"
                    }
                  ],
                  "count": 1,
                  "truncated": false,
                  "partial": false,
                  "completeness": "unknown",
                  "freshness_watermark": "2026-09-20T12:01:00.000Z"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ApmInvalid"
          },
          "401": {
            "$ref": "#/components/responses/ApmUnauthorized"
          },
          "403": {
            "$ref": "#/components/responses/ApmForbidden"
          },
          "404": {
            "$ref": "#/components/responses/ApmNotFound"
          },
          "429": {
            "$ref": "#/components/responses/ApmRateLimited"
          },
          "503": {
            "$ref": "#/components/responses/ApmWarehouseUnavailable"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/apm/services/{serviceName}/health": {
      "get": {
        "operationId": "v1ApmGetServiceHealth",
        "tags": [
          "APM Observability"
        ],
        "summary": "Read service health and dependencies",
        "description": "Returns health plus dependency aggregates. Either warehouse subquery may be unavailable; `partial`, availability booleans, and `reason` report that honestly.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "read:apm"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ApmServiceNamePath"
          },
          {
            "$ref": "#/components/parameters/ApmProjectIdQuery"
          },
          {
            "$ref": "#/components/parameters/ApmEnvironmentIdQuery"
          },
          {
            "$ref": "#/components/parameters/ApmFrom"
          },
          {
            "$ref": "#/components/parameters/ApmTo"
          },
          {
            "$ref": "#/components/parameters/ApmQueryLimit"
          }
        ],
        "responses": {
          "200": {
            "description": "Service health and dependencies.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApmServiceHealthResult"
                },
                "example": {
                  "ok": true,
                  "available": true,
                  "partial": false,
                  "reason": null,
                  "project_id": "checkout",
                  "environment_id": "prod",
                  "service_name": "checkout-api",
                  "health": {
                    "service_name": "checkout-api",
                    "trace_count": 120,
                    "error_trace_count": 3,
                    "error_rate": 0.025,
                    "p50_duration_ms": 42,
                    "p95_duration_ms": 310,
                    "completeness": "unknown",
                    "freshness_watermark": "2026-09-20T12:01:00.000Z"
                  },
                  "health_available": true,
                  "items": [
                    {
                      "source_service": "checkout-api",
                      "target_service": "payments",
                      "protocol": "http",
                      "request_count": 50,
                      "error_count": 1,
                      "p50_duration_ms": 25,
                      "p95_duration_ms": 80,
                      "p99_duration_ms": 140,
                      "freshness_watermark": "2026-09-20T12:01:00.000Z"
                    }
                  ],
                  "count": 1,
                  "dependencies_available": true,
                  "truncated": false,
                  "completeness": "unknown",
                  "freshness_watermark": "2026-09-20T12:01:00.000Z"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ApmInvalid"
          },
          "401": {
            "$ref": "#/components/responses/ApmUnauthorized"
          },
          "403": {
            "$ref": "#/components/responses/ApmForbidden"
          },
          "404": {
            "$ref": "#/components/responses/ApmNotFound"
          },
          "429": {
            "$ref": "#/components/responses/ApmRateLimited"
          },
          "503": {
            "$ref": "#/components/responses/ApmWarehouseUnavailable"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/apm/releases/{releaseId}/health": {
      "get": {
        "operationId": "v1ApmGetReleaseHealth",
        "tags": [
          "APM Observability"
        ],
        "summary": "Read release health",
        "description": "Returns bounded aggregate health rows for one release within the required project/environment and time range.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "read:apm"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ApmReleaseIdPath"
          },
          {
            "$ref": "#/components/parameters/ApmProjectIdQuery"
          },
          {
            "$ref": "#/components/parameters/ApmEnvironmentIdQuery"
          },
          {
            "$ref": "#/components/parameters/ApmFrom"
          },
          {
            "$ref": "#/components/parameters/ApmTo"
          },
          {
            "$ref": "#/components/parameters/ApmQueryLimit"
          }
        ],
        "responses": {
          "200": {
            "description": "Release health page.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApmReleaseHealthResult"
                },
                "example": {
                  "ok": true,
                  "available": true,
                  "project_id": "checkout",
                  "environment_id": "prod",
                  "release_id": "2026.09.20",
                  "items": [
                    {
                      "release_id": "2026.09.20",
                      "build_id": "build-42",
                      "trace_count": 100,
                      "error_trace_count": 2,
                      "error_rate": 0.02,
                      "p50_duration_ms": 40,
                      "p95_duration_ms": 300,
                      "completeness": "unknown",
                      "freshness_watermark": "2026-09-20T12:01:00.000Z"
                    }
                  ],
                  "count": 1,
                  "truncated": false,
                  "partial": false,
                  "completeness": "unknown",
                  "freshness_watermark": "2026-09-20T12:01:00.000Z"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ApmInvalid"
          },
          "401": {
            "$ref": "#/components/responses/ApmUnauthorized"
          },
          "403": {
            "$ref": "#/components/responses/ApmForbidden"
          },
          "404": {
            "$ref": "#/components/responses/ApmNotFound"
          },
          "429": {
            "$ref": "#/components/responses/ApmRateLimited"
          },
          "503": {
            "$ref": "#/components/responses/ApmWarehouseUnavailable"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/apm/exports": {
      "post": {
        "operationId": "v1ApmCreateExport",
        "tags": [
          "APM Observability"
        ],
        "summary": "Create an asynchronous APM export",
        "description": "Creates a tenant-scoped manifest for a range no longer than 31 days. This endpoint never returns storage references, credentials, or a download URL.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "write:apm"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ApmExportCreate"
              },
              "example": {
                "project_id": "checkout",
                "environment_id": "prod",
                "from": "2026-09-20T00:00:00.000Z",
                "to": "2026-09-21T00:00:00.000Z",
                "fact_names": [
                  "apm_spans",
                  "apm_trace_summaries"
                ],
                "purpose": "incident_review",
                "expires_in_seconds": 3600
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Pending export manifest.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApmExportStatus"
                },
                "example": {
                  "ok": true,
                  "project_id": "checkout",
                  "environment_id": "prod",
                  "export_manifest_id": "550e8400-e29b-41d4-a716-446655440000",
                  "purpose": "incident_review",
                  "fact_names": [
                    "apm_spans",
                    "apm_trace_summaries"
                  ],
                  "state": "pending",
                  "row_count": null,
                  "byte_count": null,
                  "created_at": "2026-09-21T00:00:00.000Z",
                  "expires_at": "2026-09-21T01:00:00.000Z",
                  "completed_at": null
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ApmInvalid"
          },
          "401": {
            "$ref": "#/components/responses/ApmUnauthorized"
          },
          "403": {
            "$ref": "#/components/responses/ApmForbidden"
          },
          "404": {
            "$ref": "#/components/responses/ApmNotFound"
          },
          "503": {
            "$ref": "#/components/responses/ApmControlUnavailable"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/apm/exports/{exportId}": {
      "get": {
        "operationId": "v1ApmGetExport",
        "tags": [
          "APM Observability"
        ],
        "summary": "Read asynchronous export status",
        "description": "Returns the safe manifest projection and its real asynchronous state; no object reference or signing credential is exposed.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "read:export"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ApmExportIdPath"
          }
        ],
        "responses": {
          "200": {
            "description": "Export status.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApmExportStatus"
                },
                "example": {
                  "ok": true,
                  "project_id": "checkout",
                  "environment_id": "prod",
                  "export_manifest_id": "550e8400-e29b-41d4-a716-446655440000",
                  "purpose": "incident_review",
                  "fact_names": [
                    "apm_spans"
                  ],
                  "state": "running",
                  "row_count": null,
                  "byte_count": null,
                  "created_at": "2026-09-21T00:00:00.000Z",
                  "expires_at": "2026-09-21T01:00:00.000Z",
                  "completed_at": null
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ApmInvalid"
          },
          "401": {
            "$ref": "#/components/responses/ApmUnauthorized"
          },
          "403": {
            "$ref": "#/components/responses/ApmForbidden"
          },
          "404": {
            "$ref": "#/components/responses/ApmNotFound"
          },
          "429": {
            "$ref": "#/components/responses/ApmRateLimited"
          },
          "503": {
            "$ref": "#/components/responses/ApmControlUnavailable"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/apm/exports/{exportId}/download-grant": {
      "post": {
        "operationId": "v1ApmCreateExportDownloadGrant",
        "tags": [
          "APM Observability"
        ],
        "summary": "Request an export download grant",
        "description": "Reports readiness only. Collector signing authority is intentionally unavailable, so this launch contract never returns a URL, object reference, bearer token, or credential.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "read:export"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ApmExportIdPath"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ApmDownloadGrantRequest"
              },
              "example": {
                "expires_in_seconds": 60
              }
            }
          }
        },
        "responses": {
          "400": {
            "$ref": "#/components/responses/ApmInvalid"
          },
          "401": {
            "$ref": "#/components/responses/ApmUnauthorized"
          },
          "403": {
            "$ref": "#/components/responses/ApmForbidden"
          },
          "404": {
            "$ref": "#/components/responses/ApmNotFound"
          },
          "409": {
            "description": "Export is not ready or failed.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApmGrantUnavailable"
                },
                "example": {
                  "ok": false,
                  "available": false,
                  "reason": "export_not_ready",
                  "state": "running",
                  "requestId": "req-test"
                }
              }
            }
          },
          "410": {
            "description": "Export expired or was deleted.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApmGrantUnavailable"
                },
                "example": {
                  "ok": false,
                  "available": false,
                  "reason": "export_expired",
                  "state": "expired",
                  "requestId": "req-test"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/ApmRateLimited"
          },
          "503": {
            "description": "Signing authority or control-plane storage is unavailable.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/ApmGrantUnavailable"
                    },
                    {
                      "$ref": "#/components/schemas/ApmUnavailable"
                    }
                  ]
                },
                "example": {
                  "ok": false,
                  "available": false,
                  "reason": "download_signing_unavailable",
                  "state": "available",
                  "requestId": "req-test"
                }
              }
            }
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/apm/privacy/subjects/{subjectHandle}/exports/{requestId}": {
      "get": {
        "operationId": "v1ApmGetPrivacyExport",
        "tags": [
          "APM Observability"
        ],
        "summary": "Read subject export status",
        "description": "Hashes the opaque subject handle before repository access and returns only the safe export projection. The cleartext handle and its hash are never returned.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "read:privacy_request"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ApmSubjectHandlePath"
          },
          {
            "$ref": "#/components/parameters/ApmPrivacyRequestIdPath"
          }
        ],
        "responses": {
          "200": {
            "description": "Subject export status.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApmPrivacyExportStatus"
                },
                "example": {
                  "ok": true,
                  "privacy_request_id": "dsar-42",
                  "project_id": "checkout",
                  "environment_id": "prod",
                  "export_manifest_id": "550e8400-e29b-41d4-a716-446655440000",
                  "purpose": "privacy_subject_export",
                  "fact_names": [
                    "apm_spans"
                  ],
                  "state": "pending",
                  "row_count": null,
                  "byte_count": null,
                  "created_at": "2026-09-21T00:00:00.000Z",
                  "expires_at": "2026-09-21T01:00:00.000Z",
                  "completed_at": null
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ApmInvalid"
          },
          "401": {
            "$ref": "#/components/responses/ApmUnauthorized"
          },
          "403": {
            "$ref": "#/components/responses/ApmForbidden"
          },
          "404": {
            "$ref": "#/components/responses/ApmNotFound"
          },
          "429": {
            "$ref": "#/components/responses/ApmRateLimited"
          },
          "503": {
            "$ref": "#/components/responses/ApmControlUnavailable"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/apm/privacy/subjects/{subjectHandle}/erasures/{requestId}": {
      "get": {
        "operationId": "v1ApmGetPrivacyErasure",
        "tags": [
          "APM Observability"
        ],
        "summary": "Read subject erasure status",
        "description": "Returns aggregate deletion progress only. Subject identifiers, per-store object references, SQL, credentials, and PII are never exposed.",
        "security": [
          {
            "v1_ApiKeyAuth": [
              "read:privacy_request"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ApmSubjectHandlePath"
          },
          {
            "$ref": "#/components/parameters/ApmPrivacyRequestIdPath"
          }
        ],
        "responses": {
          "200": {
            "description": "Subject erasure status.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApmErasureStatus"
                },
                "example": {
                  "ok": true,
                  "privacy_request_id": "dsar-42",
                  "project_id": "checkout",
                  "environment_id": "prod",
                  "state": "running",
                  "attempts": 1,
                  "created_at": "2026-09-21T00:00:00.000Z",
                  "updated_at": "2026-09-21T00:05:00.000Z",
                  "completed_at": null,
                  "stores": {
                    "count": 3,
                    "pending": 1,
                    "running": 1,
                    "succeeded": 1,
                    "failed": 0
                  },
                  "deleted": {
                    "rows": 120,
                    "objects": 2,
                    "bytes": 4096
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ApmInvalid"
          },
          "401": {
            "$ref": "#/components/responses/ApmUnauthorized"
          },
          "403": {
            "$ref": "#/components/responses/ApmForbidden"
          },
          "404": {
            "$ref": "#/components/responses/ApmNotFound"
          },
          "429": {
            "$ref": "#/components/responses/ApmRateLimited"
          },
          "503": {
            "$ref": "#/components/responses/ApmControlUnavailable"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/traces": {
      "post": {
        "operationId": "v1ApmIngestTraces",
        "tags": [
          "APM Ingest"
        ],
        "summary": "Ingest an OTLP/HTTP trace export",
        "description": "OTLP/HTTP trace ingestion. Any OpenTelemetry SDK or Collector OTLP/HTTP exporter can send to it: the body is a proto3-JSON `ExportTraceServiceRequest` (`application/json`) or its protobuf encoding (`application/x-protobuf`), and any other Content-Type is rejected with `415`. `Content-Encoding: gzip` or `deflate` is accepted. The collector hosts reject a wire body above 1 MiB, a decompressed body above 4 MiB, and a request with more than 500 spans, so size your exporter batches accordingly.\n\nAuthenticate with an ingestion key (`Authorization: Bearer sk_apm_...`) whose allowed signals include `traces`; a server API key is never accepted.\n\n**Hosts.** Send the request to `https://ingest.noxtica.com` (production): this is the host the Backoffice shows next to an ingestion key. The same path and credential are also served by the collector hosts listed under `servers`.\n\nPer-key and per-project rate limits apply; a limited request answers `429` with a `Retry-After` header. The limit values differ between host implementations and are not part of this contract.\n\n**Errors.** Error bodies are JSON. The collector hosts answer a `google.rpc.Status`-shaped body (`code` is the gRPC status code and `details[0].reason` the reason); the dedicated ingest hosts answer `{\"code\": <HTTP status>, \"message\": \"...\", \"error\": \"<reason>\"}`. The reason strings (for example `apm_auth_invalid`, `apm_rate_limited`) are the same on both, so branch on the HTTP status and the reason, never on `code`. Success bodies follow the OTLP wire contract and use the request's own media type.",
        "security": [
          {
            "ApmIngestKeyAuth": []
          }
        ],
        "servers": [
          {
            "url": "https://ingest.noxtica.com",
            "description": "Production ingest host"
          },
          {
            "url": "https://collect.noxtica.com",
            "description": "Production collector host (same path and credential)"
          }
        ],
        "parameters": [
          {
            "name": "Content-Encoding",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "identity",
                "gzip",
                "deflate"
              ]
            },
            "description": "Defaults to `identity` (uncompressed) when absent. Any other value is rejected with 415."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OtlpExportTraceServiceRequest"
              },
              "example": {
                "resourceSpans": [
                  {
                    "resource": {
                      "attributes": [
                        {
                          "key": "service.name",
                          "value": {
                            "stringValue": "checkout-api"
                          }
                        }
                      ]
                    },
                    "scopeSpans": [
                      {
                        "scope": {
                          "name": "@noxtica/otel-shim",
                          "version": "1.0.0"
                        },
                        "spans": [
                          {
                            "traceId": "AAAAAAAAAAAAAAAAAAAAAA==",
                            "spanId": "AAAAAAAAAAA=",
                            "name": "GET /health",
                            "kind": "SPAN_KIND_SERVER",
                            "startTimeUnixNano": "1700000000000000000",
                            "endTimeUnixNano": "1700000000010000000",
                            "status": {
                              "code": "STATUS_CODE_OK"
                            }
                          }
                        ]
                      }
                    ]
                  }
                ]
              }
            },
            "application/x-protobuf": {
              "schema": {
                "type": "string",
                "format": "binary",
                "description": "Protobuf-encoded `ExportTraceServiceRequest` — the default wire format most OpenTelemetry SDK/Collector OTLP exporters send."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Export accepted. An empty object means every span was accepted; `partialSuccess` reports spans dropped during validation without failing the whole request.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OtlpTraceIngestResult"
                },
                "examples": {
                  "all_spans_accepted": {
                    "summary": "Every span accepted.",
                    "value": {}
                  },
                  "spans_partially_rejected": {
                    "summary": "Some spans failed validation.",
                    "value": {
                      "partialSuccess": {
                        "rejectedSpans": "3",
                        "errorMessage": "One or more spans failed validation and were not accepted"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`apm_malformed_otlp_json`/`apm_malformed_otlp_protobuf` — the body does not decode as a valid `ExportTraceServiceRequest` in its declared Content-Type.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OtlpStatus"
                },
                "examples": {
                  "malformed_json": {
                    "summary": "Body is not a valid proto3-JSON ExportTraceServiceRequest.",
                    "value": {
                      "code": 3,
                      "message": "Malformed OTLP JSON: invalid_json",
                      "details": [
                        {
                          "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                          "reason": "apm_malformed_otlp_json",
                          "domain": "ingest.noxtica.com",
                          "metadata": {
                            "requestId": "req-test",
                            "retryable": "false"
                          }
                        }
                      ]
                    }
                  },
                  "malformed_protobuf": {
                    "summary": "Body does not decode as a valid ExportTraceServiceRequest protobuf message.",
                    "value": {
                      "code": 3,
                      "message": "Malformed OTLP protobuf: decode_failed",
                      "details": [
                        {
                          "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                          "reason": "apm_malformed_otlp_protobuf",
                          "domain": "ingest.noxtica.com",
                          "metadata": {
                            "requestId": "req-test",
                            "retryable": "false"
                          }
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid `sk_apm_` bearer credential, or the credential's `effective_at`/`expires_at` window excludes now. A tenant `ApiKeyAuth` `sk_` key is never accepted here.",
            "headers": {
              "WWW-Authenticate": {
                "schema": {
                  "type": "string"
                },
                "description": "On the collector hosts always `Bearer realm=\"noxtica-otlp\", charset=\"UTF-8\"`; the ingest hosts do not send it."
              },
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OtlpStatus"
                },
                "examples": {
                  "auth_missing": {
                    "summary": "No Authorization header.",
                    "value": {
                      "code": 16,
                      "message": "Authentication failed",
                      "details": [
                        {
                          "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                          "reason": "apm_auth_missing",
                          "domain": "ingest.noxtica.com",
                          "metadata": {
                            "requestId": "req-test",
                            "retryable": "false"
                          }
                        }
                      ]
                    }
                  },
                  "auth_invalid": {
                    "summary": "Credential does not resolve to an active key.",
                    "value": {
                      "code": 16,
                      "message": "Authentication failed",
                      "details": [
                        {
                          "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                          "reason": "apm_auth_invalid",
                          "domain": "ingest.noxtica.com",
                          "metadata": {
                            "requestId": "req-test",
                            "retryable": "false"
                          }
                        }
                      ]
                    }
                  },
                  "auth_expired": {
                    "summary": "now is outside [effective_at, expires_at).",
                    "value": {
                      "code": 16,
                      "message": "Authentication failed",
                      "details": [
                        {
                          "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                          "reason": "apm_auth_expired",
                          "domain": "ingest.noxtica.com",
                          "metadata": {
                            "requestId": "req-test",
                            "retryable": "false"
                          }
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The credential is active but not authorized for trace ingest.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OtlpStatus"
                },
                "examples": {
                  "scope_denied": {
                    "summary": "\"traces\" is not in the credential's allowed_signals.",
                    "value": {
                      "code": 7,
                      "message": "Trace ingest is not authorized",
                      "details": [
                        {
                          "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                          "reason": "apm_scope_denied",
                          "domain": "ingest.noxtica.com",
                          "metadata": {
                            "requestId": "req-test",
                            "retryable": "false"
                          }
                        }
                      ]
                    }
                  },
                  "purpose_disabled": {
                    "summary": "The credential's purpose_enabled flag is 0.",
                    "value": {
                      "code": 7,
                      "message": "Trace ingest is not authorized",
                      "details": [
                        {
                          "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                          "reason": "apm_purpose_disabled",
                          "domain": "ingest.noxtica.com",
                          "metadata": {
                            "requestId": "req-test",
                            "retryable": "false"
                          }
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "The wire or decompressed body exceeds its byte cap, or the request carries more than 500 spans.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OtlpStatus"
                },
                "examples": {
                  "body_too_large": {
                    "summary": "Wire body exceeds the 1 MiB cap.",
                    "value": {
                      "code": 8,
                      "message": "Request body exceeds the OTLP JSON limit",
                      "details": [
                        {
                          "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                          "reason": "apm_body_too_large",
                          "domain": "ingest.noxtica.com",
                          "metadata": {
                            "requestId": "req-test",
                            "retryable": "false"
                          }
                        }
                      ]
                    }
                  },
                  "decompressed_too_large": {
                    "summary": "Decompressed body exceeds the 4 MiB cap.",
                    "value": {
                      "code": 8,
                      "message": "Decompressed request body exceeds the OTLP JSON limit",
                      "details": [
                        {
                          "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                          "reason": "apm_body_too_large",
                          "domain": "ingest.noxtica.com",
                          "metadata": {
                            "requestId": "req-test",
                            "retryable": "false"
                          }
                        }
                      ]
                    }
                  },
                  "batch_too_large": {
                    "summary": "More than 500 spans in one request.",
                    "value": {
                      "code": 8,
                      "message": "A request may contain at most 500 spans",
                      "details": [
                        {
                          "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                          "reason": "apm_batch_too_large",
                          "domain": "ingest.noxtica.com",
                          "metadata": {
                            "requestId": "req-test",
                            "retryable": "false"
                          }
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "415": {
            "description": "Content-Type is not `application/json`, or Content-Encoding is set to a value other than `identity`, `gzip`, or `deflate`.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OtlpStatus"
                },
                "examples": {
                  "unsupported_content_type": {
                    "summary": "Content-Type header is missing or not application/json.",
                    "value": {
                      "code": 3,
                      "message": "Content-Type must be application/json",
                      "details": [
                        {
                          "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                          "reason": "apm_unsupported_media_type",
                          "domain": "ingest.noxtica.com",
                          "metadata": {
                            "requestId": "req-test",
                            "retryable": "false"
                          }
                        }
                      ]
                    }
                  },
                  "unsupported_content_encoding": {
                    "summary": "Content-Encoding is set to something other than identity/gzip/deflate.",
                    "value": {
                      "code": 3,
                      "message": "Unsupported Content-Encoding",
                      "details": [
                        {
                          "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                          "reason": "apm_unsupported_media_type",
                          "domain": "ingest.noxtica.com",
                          "metadata": {
                            "requestId": "req-test",
                            "retryable": "false"
                          }
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Trace ingest rate limit exceeded (600 requests / 60s per `tenantId:projectId`).",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the bucket allows another request."
              },
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OtlpStatus"
                },
                "example": {
                  "code": 8,
                  "message": "Trace ingest rate limit exceeded",
                  "details": [
                    {
                      "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                      "reason": "apm_rate_limited",
                      "domain": "ingest.noxtica.com",
                      "metadata": {
                        "requestId": "req-test",
                        "retryable": "true"
                      }
                    }
                  ]
                }
              }
            }
          },
          "503": {
            "description": "The tenant authority scope could not be confirmed, or the durable ingest queue is unavailable.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Always `5` on this status."
              },
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OtlpStatus"
                },
                "examples": {
                  "authority_unavailable": {
                    "summary": "Tenant authority scope confirmation failed.",
                    "value": {
                      "code": 14,
                      "message": "Authority unavailable",
                      "details": [
                        {
                          "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                          "reason": "apm_authority_unavailable",
                          "domain": "ingest.noxtica.com",
                          "metadata": {
                            "requestId": "req-test",
                            "retryable": "true"
                          }
                        }
                      ]
                    }
                  },
                  "queue_unavailable": {
                    "summary": "The durable ingest queue binding is missing or rejected the message.",
                    "value": {
                      "code": 14,
                      "message": "Trace ingest queue is unavailable",
                      "details": [
                        {
                          "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                          "reason": "apm_queue_unavailable",
                          "domain": "ingest.noxtica.com",
                          "metadata": {
                            "requestId": "req-test",
                            "retryable": "true"
                          }
                        }
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "x-noxtica-status": "partial"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/metrics": {
      "post": {
        "operationId": "v1ApmIngestMetrics",
        "tags": [
          "APM Ingest"
        ],
        "summary": "Ingest an OTLP/HTTP metrics export",
        "description": "OTLP/HTTP metrics ingestion: a proto3-JSON `ExportMetricsServiceRequest` (`application/json`) or its protobuf encoding (`application/x-protobuf`); any other Content-Type is rejected with `415`. `Content-Encoding: gzip` or `deflate` is accepted. The collector hosts reject a wire body above 1 MiB, a decompressed body above 4 MiB, and a request with more than 500 data points across every metric's `gauge`, `sum`, `histogram`, `exponentialHistogram` and `summary` arrays.\n\nAuthenticate with an ingestion key (`Authorization: Bearer sk_apm_...`) whose allowed signals include `metrics`.\n\n**Hosts.** Send the request to `https://ingest.noxtica.com` (production): this is the host the Backoffice shows next to an ingestion key. The same path and credential are also served by the collector hosts listed under `servers`.\n\nPer-key and per-project rate limits apply; a limited request answers `429` with a `Retry-After` header. The limit values differ between host implementations and are not part of this contract.\n\n**Errors.** Error bodies are JSON. The collector hosts answer a `google.rpc.Status`-shaped body (`code` is the gRPC status code and `details[0].reason` the reason); the dedicated ingest hosts answer `{\"code\": <HTTP status>, \"message\": \"...\", \"error\": \"<reason>\"}`. The reason strings (for example `apm_auth_invalid`, `apm_rate_limited`) are the same on both, so branch on the HTTP status and the reason, never on `code`. Success bodies follow the OTLP wire contract and use the request's own media type.",
        "security": [
          {
            "ApmIngestKeyAuth": []
          }
        ],
        "servers": [
          {
            "url": "https://ingest.noxtica.com",
            "description": "Production ingest host"
          },
          {
            "url": "https://collect.noxtica.com",
            "description": "Production collector host (same path and credential)"
          }
        ],
        "parameters": [
          {
            "name": "Content-Encoding",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "identity",
                "gzip",
                "deflate"
              ]
            },
            "description": "Defaults to `identity` (uncompressed) when absent. Any other value is rejected with 415."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OtlpExportMetricsServiceRequest"
              },
              "example": {
                "resourceMetrics": [
                  {
                    "resource": {
                      "attributes": [
                        {
                          "key": "service.name",
                          "value": {
                            "stringValue": "checkout-api"
                          }
                        }
                      ]
                    },
                    "scopeMetrics": [
                      {
                        "scope": {
                          "name": "@noxtica/otel-shim",
                          "version": "1.0.0"
                        },
                        "metrics": [
                          {
                            "name": "http.server.duration",
                            "unit": "ms",
                            "gauge": {
                              "dataPoints": [
                                {
                                  "timeUnixNano": "1700000000000000000",
                                  "asDouble": 12.5
                                }
                              ]
                            }
                          }
                        ]
                      }
                    ]
                  }
                ]
              }
            },
            "application/x-protobuf": {
              "schema": {
                "type": "string",
                "format": "binary",
                "description": "Protobuf-encoded `ExportMetricsServiceRequest` — the default wire format most OpenTelemetry SDK/Collector OTLP exporters send."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Export accepted. An empty object means every data point was accepted; `partialSuccess` reports data points dropped during validation without failing the whole request.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OtlpMetricsIngestResult"
                },
                "examples": {
                  "all_points_accepted": {
                    "summary": "Every data point accepted.",
                    "value": {}
                  },
                  "points_partially_rejected": {
                    "summary": "Some data points failed validation.",
                    "value": {
                      "partialSuccess": {
                        "rejectedDataPoints": "3",
                        "errorMessage": "One or more metric data points failed validation and were not accepted"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`apm_malformed_metrics_payload` — the body does not decode as a valid `ExportMetricsServiceRequest` in its declared Content-Type.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OtlpStatus"
                },
                "example": {
                  "code": 3,
                  "message": "Malformed OTLP metrics payload: decode_failed",
                  "details": [
                    {
                      "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                      "reason": "apm_malformed_metrics_payload",
                      "domain": "ingest.noxtica.com",
                      "metadata": {
                        "requestId": "req-test",
                        "retryable": "false"
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid `sk_apm_` bearer credential, or the credential's `effective_at`/`expires_at` window excludes now. A tenant `ApiKeyAuth` `sk_` key is never accepted here.",
            "headers": {
              "WWW-Authenticate": {
                "schema": {
                  "type": "string"
                },
                "description": "On the collector hosts always `Bearer realm=\"noxtica-otlp\", charset=\"UTF-8\"`; the ingest hosts do not send it."
              },
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OtlpStatus"
                },
                "examples": {
                  "auth_missing": {
                    "summary": "No Authorization header.",
                    "value": {
                      "code": 16,
                      "message": "Authentication failed",
                      "details": [
                        {
                          "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                          "reason": "apm_auth_missing",
                          "domain": "ingest.noxtica.com",
                          "metadata": {
                            "requestId": "req-test",
                            "retryable": "false"
                          }
                        }
                      ]
                    }
                  },
                  "auth_invalid": {
                    "summary": "Credential does not resolve to an active key.",
                    "value": {
                      "code": 16,
                      "message": "Authentication failed",
                      "details": [
                        {
                          "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                          "reason": "apm_auth_invalid",
                          "domain": "ingest.noxtica.com",
                          "metadata": {
                            "requestId": "req-test",
                            "retryable": "false"
                          }
                        }
                      ]
                    }
                  },
                  "auth_expired": {
                    "summary": "now is outside [effective_at, expires_at).",
                    "value": {
                      "code": 16,
                      "message": "Authentication failed",
                      "details": [
                        {
                          "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                          "reason": "apm_auth_expired",
                          "domain": "ingest.noxtica.com",
                          "metadata": {
                            "requestId": "req-test",
                            "retryable": "false"
                          }
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The credential is active but not authorized for metrics ingest.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OtlpStatus"
                },
                "examples": {
                  "scope_denied": {
                    "summary": "\"metrics\" is not in the credential's allowed_signals.",
                    "value": {
                      "code": 7,
                      "message": "Metrics ingest is not authorized",
                      "details": [
                        {
                          "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                          "reason": "apm_scope_denied",
                          "domain": "ingest.noxtica.com",
                          "metadata": {
                            "requestId": "req-test",
                            "retryable": "false"
                          }
                        }
                      ]
                    }
                  },
                  "purpose_disabled": {
                    "summary": "The credential's purpose_enabled flag is 0.",
                    "value": {
                      "code": 7,
                      "message": "Metrics ingest is not authorized",
                      "details": [
                        {
                          "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                          "reason": "apm_purpose_disabled",
                          "domain": "ingest.noxtica.com",
                          "metadata": {
                            "requestId": "req-test",
                            "retryable": "false"
                          }
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "The wire or decompressed body exceeds its byte cap, or the request carries more than 500 data points.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OtlpStatus"
                },
                "examples": {
                  "body_too_large": {
                    "summary": "Wire body exceeds the 1 MiB cap.",
                    "value": {
                      "code": 8,
                      "message": "Request body exceeds the OTLP payload limit",
                      "details": [
                        {
                          "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                          "reason": "apm_body_too_large",
                          "domain": "ingest.noxtica.com",
                          "metadata": {
                            "requestId": "req-test",
                            "retryable": "false"
                          }
                        }
                      ]
                    }
                  },
                  "decompressed_too_large": {
                    "summary": "Decompressed body exceeds the 4 MiB cap.",
                    "value": {
                      "code": 8,
                      "message": "Decompressed request body exceeds the OTLP payload limit",
                      "details": [
                        {
                          "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                          "reason": "apm_body_too_large",
                          "domain": "ingest.noxtica.com",
                          "metadata": {
                            "requestId": "req-test",
                            "retryable": "false"
                          }
                        }
                      ]
                    }
                  },
                  "batch_too_large": {
                    "summary": "More than 500 data points in one request.",
                    "value": {
                      "code": 8,
                      "message": "A request may contain at most 500 data points",
                      "details": [
                        {
                          "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                          "reason": "apm_batch_too_large",
                          "domain": "ingest.noxtica.com",
                          "metadata": {
                            "requestId": "req-test",
                            "retryable": "false"
                          }
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "415": {
            "description": "Content-Type is not `application/json` or `application/x-protobuf`, or Content-Encoding is set to a value other than `identity`, `gzip`, or `deflate`.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OtlpStatus"
                },
                "example": {
                  "code": 3,
                  "message": "Content-Type must be application/json or application/x-protobuf",
                  "details": [
                    {
                      "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                      "reason": "apm_unsupported_media_type",
                      "domain": "ingest.noxtica.com",
                      "metadata": {
                        "requestId": "req-test",
                        "retryable": "false"
                      }
                    }
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Metrics ingest rate limit exceeded (600 requests / 60s per `tenantId:projectId`).",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the bucket allows another request."
              },
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OtlpStatus"
                },
                "example": {
                  "code": 8,
                  "message": "Metrics ingest rate limit exceeded",
                  "details": [
                    {
                      "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                      "reason": "apm_rate_limited",
                      "domain": "ingest.noxtica.com",
                      "metadata": {
                        "requestId": "req-test",
                        "retryable": "true"
                      }
                    }
                  ]
                }
              }
            }
          },
          "503": {
            "description": "The tenant authority scope could not be confirmed, or the durable ingest queue is unavailable.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Always `5` on this status."
              },
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OtlpStatus"
                },
                "examples": {
                  "authority_unavailable": {
                    "summary": "Tenant authority scope confirmation failed.",
                    "value": {
                      "code": 14,
                      "message": "Authority unavailable",
                      "details": [
                        {
                          "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                          "reason": "apm_authority_unavailable",
                          "domain": "ingest.noxtica.com",
                          "metadata": {
                            "requestId": "req-test",
                            "retryable": "true"
                          }
                        }
                      ]
                    }
                  },
                  "queue_unavailable": {
                    "summary": "The durable ingest queue binding is missing or rejected the message.",
                    "value": {
                      "code": 14,
                      "message": "Metrics ingest queue is unavailable",
                      "details": [
                        {
                          "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                          "reason": "apm_queue_unavailable",
                          "domain": "ingest.noxtica.com",
                          "metadata": {
                            "requestId": "req-test",
                            "retryable": "true"
                          }
                        }
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "x-noxtica-status": "partial"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/logs": {
      "post": {
        "operationId": "v1ApmIngestLogs",
        "tags": [
          "APM Ingest"
        ],
        "summary": "Ingest an OTLP/HTTP logs export",
        "description": "OTLP/HTTP logs ingestion: a proto3-JSON `ExportLogsServiceRequest` (`application/json`) or its protobuf encoding (`application/x-protobuf`); any other Content-Type is rejected with `415`. `Content-Encoding: gzip` or `deflate` is accepted. The collector hosts reject a wire body above 1 MiB, a decompressed body above 4 MiB, and a request with more than 500 log records across every `resourceLogs[].scopeLogs[].logRecords[]`.\n\nAuthenticate with an ingestion key (`Authorization: Bearer sk_apm_...`) whose allowed signals include `logs`.\n\n**Hosts.** Send the request to `https://ingest.noxtica.com` (production): this is the host the Backoffice shows next to an ingestion key. The same path and credential are also served by the collector hosts listed under `servers`.\n\nPer-key and per-project rate limits apply; a limited request answers `429` with a `Retry-After` header. The limit values differ between host implementations and are not part of this contract.\n\n**Errors.** Error bodies are JSON. The collector hosts answer a `google.rpc.Status`-shaped body (`code` is the gRPC status code and `details[0].reason` the reason); the dedicated ingest hosts answer `{\"code\": <HTTP status>, \"message\": \"...\", \"error\": \"<reason>\"}`. The reason strings (for example `apm_auth_invalid`, `apm_rate_limited`) are the same on both, so branch on the HTTP status and the reason, never on `code`. Success bodies follow the OTLP wire contract and use the request's own media type.",
        "security": [
          {
            "ApmIngestKeyAuth": []
          }
        ],
        "servers": [
          {
            "url": "https://ingest.noxtica.com",
            "description": "Production ingest host"
          },
          {
            "url": "https://collect.noxtica.com",
            "description": "Production collector host (same path and credential)"
          }
        ],
        "parameters": [
          {
            "name": "Content-Encoding",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "identity",
                "gzip",
                "deflate"
              ]
            },
            "description": "Defaults to `identity` (uncompressed) when absent. Any other value is rejected with 415."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OtlpExportLogsServiceRequest"
              },
              "example": {
                "resourceLogs": [
                  {
                    "resource": {
                      "attributes": [
                        {
                          "key": "service.name",
                          "value": {
                            "stringValue": "checkout-api"
                          }
                        }
                      ]
                    },
                    "scopeLogs": [
                      {
                        "scope": {
                          "name": "@noxtica/otel-shim",
                          "version": "1.0.0"
                        },
                        "logRecords": [
                          {
                            "timeUnixNano": "1700000000000000000",
                            "severityNumber": 9,
                            "severityText": "INFO",
                            "body": {
                              "stringValue": "order placed"
                            }
                          }
                        ]
                      }
                    ]
                  }
                ]
              }
            },
            "application/x-protobuf": {
              "schema": {
                "type": "string",
                "format": "binary",
                "description": "Protobuf-encoded `ExportLogsServiceRequest` — the default wire format most OpenTelemetry SDK/Collector OTLP exporters send."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Export accepted. An empty object means every log record was accepted; `partialSuccess` reports log records dropped during validation without failing the whole request.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OtlpLogsIngestResult"
                },
                "examples": {
                  "all_records_accepted": {
                    "summary": "Every log record accepted.",
                    "value": {}
                  },
                  "records_partially_rejected": {
                    "summary": "Some log records failed validation.",
                    "value": {
                      "partialSuccess": {
                        "rejectedLogRecords": "3",
                        "errorMessage": "One or more log records failed validation and were not accepted"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`apm_malformed_logs_payload` — the body does not decode as a valid `ExportLogsServiceRequest` in its declared Content-Type.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OtlpStatus"
                },
                "example": {
                  "code": 3,
                  "message": "Malformed OTLP logs payload: decode_failed",
                  "details": [
                    {
                      "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                      "reason": "apm_malformed_logs_payload",
                      "domain": "ingest.noxtica.com",
                      "metadata": {
                        "requestId": "req-test",
                        "retryable": "false"
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid `sk_apm_` bearer credential, or the credential's `effective_at`/`expires_at` window excludes now. A tenant `ApiKeyAuth` `sk_` key is never accepted here.",
            "headers": {
              "WWW-Authenticate": {
                "schema": {
                  "type": "string"
                },
                "description": "On the collector hosts always `Bearer realm=\"noxtica-otlp\", charset=\"UTF-8\"`; the ingest hosts do not send it."
              },
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OtlpStatus"
                },
                "examples": {
                  "auth_missing": {
                    "summary": "No Authorization header.",
                    "value": {
                      "code": 16,
                      "message": "Authentication failed",
                      "details": [
                        {
                          "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                          "reason": "apm_auth_missing",
                          "domain": "ingest.noxtica.com",
                          "metadata": {
                            "requestId": "req-test",
                            "retryable": "false"
                          }
                        }
                      ]
                    }
                  },
                  "auth_invalid": {
                    "summary": "Credential does not resolve to an active key.",
                    "value": {
                      "code": 16,
                      "message": "Authentication failed",
                      "details": [
                        {
                          "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                          "reason": "apm_auth_invalid",
                          "domain": "ingest.noxtica.com",
                          "metadata": {
                            "requestId": "req-test",
                            "retryable": "false"
                          }
                        }
                      ]
                    }
                  },
                  "auth_expired": {
                    "summary": "now is outside [effective_at, expires_at).",
                    "value": {
                      "code": 16,
                      "message": "Authentication failed",
                      "details": [
                        {
                          "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                          "reason": "apm_auth_expired",
                          "domain": "ingest.noxtica.com",
                          "metadata": {
                            "requestId": "req-test",
                            "retryable": "false"
                          }
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The credential is active but not authorized for logs ingest.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OtlpStatus"
                },
                "examples": {
                  "scope_denied": {
                    "summary": "\"logs\" is not in the credential's allowed_signals.",
                    "value": {
                      "code": 7,
                      "message": "Logs ingest is not authorized",
                      "details": [
                        {
                          "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                          "reason": "apm_scope_denied",
                          "domain": "ingest.noxtica.com",
                          "metadata": {
                            "requestId": "req-test",
                            "retryable": "false"
                          }
                        }
                      ]
                    }
                  },
                  "purpose_disabled": {
                    "summary": "The credential's purpose_enabled flag is 0.",
                    "value": {
                      "code": 7,
                      "message": "Logs ingest is not authorized",
                      "details": [
                        {
                          "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                          "reason": "apm_purpose_disabled",
                          "domain": "ingest.noxtica.com",
                          "metadata": {
                            "requestId": "req-test",
                            "retryable": "false"
                          }
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "The wire or decompressed body exceeds its byte cap, or the request carries more than 500 log records.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OtlpStatus"
                },
                "examples": {
                  "body_too_large": {
                    "summary": "Wire body exceeds the 1 MiB cap.",
                    "value": {
                      "code": 8,
                      "message": "Request body exceeds the OTLP payload limit",
                      "details": [
                        {
                          "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                          "reason": "apm_body_too_large",
                          "domain": "ingest.noxtica.com",
                          "metadata": {
                            "requestId": "req-test",
                            "retryable": "false"
                          }
                        }
                      ]
                    }
                  },
                  "decompressed_too_large": {
                    "summary": "Decompressed body exceeds the 4 MiB cap.",
                    "value": {
                      "code": 8,
                      "message": "Decompressed request body exceeds the OTLP payload limit",
                      "details": [
                        {
                          "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                          "reason": "apm_body_too_large",
                          "domain": "ingest.noxtica.com",
                          "metadata": {
                            "requestId": "req-test",
                            "retryable": "false"
                          }
                        }
                      ]
                    }
                  },
                  "batch_too_large": {
                    "summary": "More than 500 log records in one request.",
                    "value": {
                      "code": 8,
                      "message": "A request may contain at most 500 log records",
                      "details": [
                        {
                          "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                          "reason": "apm_batch_too_large",
                          "domain": "ingest.noxtica.com",
                          "metadata": {
                            "requestId": "req-test",
                            "retryable": "false"
                          }
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "415": {
            "description": "Content-Type is not `application/json` or `application/x-protobuf`, or Content-Encoding is set to a value other than `identity`, `gzip`, or `deflate`.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OtlpStatus"
                },
                "example": {
                  "code": 3,
                  "message": "Content-Type must be application/json or application/x-protobuf",
                  "details": [
                    {
                      "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                      "reason": "apm_unsupported_media_type",
                      "domain": "ingest.noxtica.com",
                      "metadata": {
                        "requestId": "req-test",
                        "retryable": "false"
                      }
                    }
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Logs ingest rate limit exceeded (600 requests / 60s per `tenantId:projectId`).",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the bucket allows another request."
              },
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OtlpStatus"
                },
                "example": {
                  "code": 8,
                  "message": "Logs ingest rate limit exceeded",
                  "details": [
                    {
                      "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                      "reason": "apm_rate_limited",
                      "domain": "ingest.noxtica.com",
                      "metadata": {
                        "requestId": "req-test",
                        "retryable": "true"
                      }
                    }
                  ]
                }
              }
            }
          },
          "503": {
            "description": "The tenant authority scope could not be confirmed, or the durable ingest queue is unavailable.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Always `5` on this status."
              },
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OtlpStatus"
                },
                "examples": {
                  "authority_unavailable": {
                    "summary": "Tenant authority scope confirmation failed.",
                    "value": {
                      "code": 14,
                      "message": "Authority unavailable",
                      "details": [
                        {
                          "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                          "reason": "apm_authority_unavailable",
                          "domain": "ingest.noxtica.com",
                          "metadata": {
                            "requestId": "req-test",
                            "retryable": "true"
                          }
                        }
                      ]
                    }
                  },
                  "queue_unavailable": {
                    "summary": "The durable ingest queue binding is missing or rejected the message.",
                    "value": {
                      "code": 14,
                      "message": "Logs ingest queue is unavailable",
                      "details": [
                        {
                          "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                          "reason": "apm_queue_unavailable",
                          "domain": "ingest.noxtica.com",
                          "metadata": {
                            "requestId": "req-test",
                            "retryable": "true"
                          }
                        }
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "x-noxtica-status": "partial"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/profiles": {
      "post": {
        "operationId": "v1ApmIngestProfiles",
        "tags": [
          "APM Ingest"
        ],
        "summary": "Ingest an OTLP/HTTP JSON profiles export",
        "description": "OTLP/HTTP JSON profiles ingestion, a proto3-JSON `ProfilesData` (`opentelemetry.proto.profiles.v1development`; profiling is still an OpenTelemetry development signal). Unlike traces, metrics and logs, `application/json` is the only media type on the collector hosts: protobuf is rejected with `415`. `Content-Encoding: gzip` or `deflate` is accepted. The collector hosts reject a wire body above 2 MiB, a decompressed body above 8 MiB, and a request with more than 20 profiles across every `resourceProfiles[].scopeProfiles[].profiles[]`. The dedicated ingest hosts additionally accept the multipart upload format sent by the Noxtica host agent; that format is internal to the agent and not part of this contract.\n\nEach accepted profile's raw bytes are stored before the row is queued, so if profile storage is unavailable the whole request fails with `503 apm_profile_storage_unavailable` even though authentication and validation succeeded.\n\nAuthenticate with an ingestion key (`Authorization: Bearer sk_apm_...`) whose allowed signals include `profiles`.\n\n**Hosts.** Send the request to `https://ingest.noxtica.com` (production): this is the host the Backoffice shows next to an ingestion key. The same path and credential are also served by the collector hosts listed under `servers`.\n\nPer-key and per-project rate limits apply; a limited request answers `429` with a `Retry-After` header. The limit values differ between host implementations and are not part of this contract.\n\n**Errors.** Error bodies are JSON. The collector hosts answer a `google.rpc.Status`-shaped body (`code` is the gRPC status code and `details[0].reason` the reason); the dedicated ingest hosts answer `{\"code\": <HTTP status>, \"message\": \"...\", \"error\": \"<reason>\"}`. The reason strings (for example `apm_auth_invalid`, `apm_rate_limited`) are the same on both, so branch on the HTTP status and the reason, never on `code`. Success bodies follow the OTLP wire contract and use the request's own media type.",
        "security": [
          {
            "ApmIngestKeyAuth": []
          }
        ],
        "servers": [
          {
            "url": "https://ingest.noxtica.com",
            "description": "Production ingest host"
          },
          {
            "url": "https://collect.noxtica.com",
            "description": "Production collector host (same path and credential)"
          }
        ],
        "parameters": [
          {
            "name": "Content-Encoding",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "identity",
                "gzip",
                "deflate"
              ]
            },
            "description": "Defaults to `identity` (uncompressed) when absent. Any other value is rejected with 415."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OtlpProfilesData"
              },
              "example": {
                "resourceProfiles": [
                  {
                    "resource": {
                      "attributes": [
                        {
                          "key": "service.name",
                          "value": {
                            "stringValue": "checkout-api"
                          }
                        }
                      ]
                    },
                    "scopeProfiles": [
                      {
                        "scope": {
                          "name": "@noxtica/otel-shim",
                          "version": "1.0.0"
                        },
                        "profiles": [
                          {
                            "profileId": "AAAAAAAAAAAAAAAAAAAAAA==",
                            "startTimeUnixNano": "1700000000000000000",
                            "endTimeUnixNano": "1700000001000000000"
                          }
                        ]
                      }
                    ]
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Export accepted. An empty object means every profile was accepted and persisted; `partialSuccess` reports profiles dropped during validation, or stored with an unrecognized `profileType`, without failing the whole request.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OtlpProfilesIngestResult"
                },
                "examples": {
                  "all_profiles_accepted": {
                    "summary": "Every profile accepted.",
                    "value": {}
                  },
                  "profiles_partially_rejected": {
                    "summary": "Some profiles failed validation.",
                    "value": {
                      "partialSuccess": {
                        "rejectedProfiles": "1",
                        "errorMessage": "1 profile(s) failed validation and were not accepted"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`apm_malformed_profile_json` — the body is not a valid proto3-JSON `ProfilesData`.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OtlpStatus"
                },
                "example": {
                  "code": 3,
                  "message": "Malformed OTLP profiles JSON: invalid_resource_profiles",
                  "details": [
                    {
                      "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                      "reason": "apm_malformed_profile_json",
                      "domain": "ingest.noxtica.com",
                      "metadata": {
                        "requestId": "req-test",
                        "retryable": "false"
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid `sk_apm_` bearer credential, or the credential's `effective_at`/`expires_at` window excludes now. A tenant `ApiKeyAuth` `sk_` key is never accepted here.",
            "headers": {
              "WWW-Authenticate": {
                "schema": {
                  "type": "string"
                },
                "description": "On the collector hosts always `Bearer realm=\"noxtica-otlp\", charset=\"UTF-8\"`; the ingest hosts do not send it."
              },
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OtlpStatus"
                },
                "examples": {
                  "auth_missing": {
                    "summary": "No Authorization header.",
                    "value": {
                      "code": 16,
                      "message": "Authentication failed",
                      "details": [
                        {
                          "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                          "reason": "apm_auth_missing",
                          "domain": "ingest.noxtica.com",
                          "metadata": {
                            "requestId": "req-test",
                            "retryable": "false"
                          }
                        }
                      ]
                    }
                  },
                  "auth_invalid": {
                    "summary": "Credential does not resolve to an active key.",
                    "value": {
                      "code": 16,
                      "message": "Authentication failed",
                      "details": [
                        {
                          "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                          "reason": "apm_auth_invalid",
                          "domain": "ingest.noxtica.com",
                          "metadata": {
                            "requestId": "req-test",
                            "retryable": "false"
                          }
                        }
                      ]
                    }
                  },
                  "auth_expired": {
                    "summary": "now is outside [effective_at, expires_at).",
                    "value": {
                      "code": 16,
                      "message": "Authentication failed",
                      "details": [
                        {
                          "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                          "reason": "apm_auth_expired",
                          "domain": "ingest.noxtica.com",
                          "metadata": {
                            "requestId": "req-test",
                            "retryable": "false"
                          }
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The credential is active but not authorized for profile ingest.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OtlpStatus"
                },
                "examples": {
                  "scope_denied": {
                    "summary": "\"profiles\" is not in the credential's allowed_signals.",
                    "value": {
                      "code": 7,
                      "message": "Profile ingest is not authorized",
                      "details": [
                        {
                          "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                          "reason": "apm_scope_denied",
                          "domain": "ingest.noxtica.com",
                          "metadata": {
                            "requestId": "req-test",
                            "retryable": "false"
                          }
                        }
                      ]
                    }
                  },
                  "purpose_disabled": {
                    "summary": "The credential's purpose_enabled flag is 0.",
                    "value": {
                      "code": 7,
                      "message": "Profile ingest is not authorized",
                      "details": [
                        {
                          "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                          "reason": "apm_purpose_disabled",
                          "domain": "ingest.noxtica.com",
                          "metadata": {
                            "requestId": "req-test",
                            "retryable": "false"
                          }
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "The wire or decompressed body exceeds its byte cap, or the request carries more than 20 profiles.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OtlpStatus"
                },
                "examples": {
                  "body_too_large": {
                    "summary": "Wire body exceeds the 2 MiB cap.",
                    "value": {
                      "code": 8,
                      "message": "Request body exceeds the OTLP profiles limit",
                      "details": [
                        {
                          "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                          "reason": "apm_body_too_large",
                          "domain": "ingest.noxtica.com",
                          "metadata": {
                            "requestId": "req-test",
                            "retryable": "false"
                          }
                        }
                      ]
                    }
                  },
                  "decompressed_too_large": {
                    "summary": "Decompressed body exceeds the 8 MiB cap.",
                    "value": {
                      "code": 8,
                      "message": "Decompressed request body exceeds the OTLP profiles limit",
                      "details": [
                        {
                          "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                          "reason": "apm_body_too_large",
                          "domain": "ingest.noxtica.com",
                          "metadata": {
                            "requestId": "req-test",
                            "retryable": "false"
                          }
                        }
                      ]
                    }
                  },
                  "batch_too_large": {
                    "summary": "More than 20 profiles in one request.",
                    "value": {
                      "code": 8,
                      "message": "A request may contain at most 20 profiles",
                      "details": [
                        {
                          "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                          "reason": "apm_batch_too_large",
                          "domain": "ingest.noxtica.com",
                          "metadata": {
                            "requestId": "req-test",
                            "retryable": "false"
                          }
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "415": {
            "description": "Content-Type is not `application/json` (protobuf is never accepted on this route), or Content-Encoding is set to a value other than `identity`, `gzip`, or `deflate`.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OtlpStatus"
                },
                "example": {
                  "code": 3,
                  "message": "Content-Type must be application/json",
                  "details": [
                    {
                      "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                      "reason": "apm_unsupported_media_type",
                      "domain": "ingest.noxtica.com",
                      "metadata": {
                        "requestId": "req-test",
                        "retryable": "false"
                      }
                    }
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Profile ingest rate limit exceeded (600 requests / 60s per `tenantId:projectId`).",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the bucket allows another request."
              },
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OtlpStatus"
                },
                "example": {
                  "code": 8,
                  "message": "Profile ingest rate limit exceeded",
                  "details": [
                    {
                      "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                      "reason": "apm_rate_limited",
                      "domain": "ingest.noxtica.com",
                      "metadata": {
                        "requestId": "req-test",
                        "retryable": "true"
                      }
                    }
                  ]
                }
              }
            }
          },
          "503": {
            "description": "The tenant authority scope could not be confirmed, the profile object store is unavailable, or the durable ingest queue is unavailable.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Always `5` on this status."
              },
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OtlpStatus"
                },
                "examples": {
                  "authority_unavailable": {
                    "summary": "Tenant authority scope confirmation failed.",
                    "value": {
                      "code": 14,
                      "message": "Authority unavailable",
                      "details": [
                        {
                          "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                          "reason": "apm_authority_unavailable",
                          "domain": "ingest.noxtica.com",
                          "metadata": {
                            "requestId": "req-test",
                            "retryable": "true"
                          }
                        }
                      ]
                    }
                  },
                  "profile_storage_unavailable": {
                    "summary": "The profile-payload object store binding is missing or rejected the write.",
                    "value": {
                      "code": 14,
                      "message": "Profile object storage is unavailable",
                      "details": [
                        {
                          "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                          "reason": "apm_profile_storage_unavailable",
                          "domain": "ingest.noxtica.com",
                          "metadata": {
                            "requestId": "req-test",
                            "retryable": "true"
                          }
                        }
                      ]
                    }
                  },
                  "queue_unavailable": {
                    "summary": "The durable ingest queue binding is missing or rejected the message.",
                    "value": {
                      "code": 14,
                      "message": "Profile ingest queue is unavailable",
                      "details": [
                        {
                          "@type": "type.googleapis.com/google.rpc.ErrorInfo",
                          "reason": "apm_queue_unavailable",
                          "domain": "ingest.noxtica.com",
                          "metadata": {
                            "requestId": "req-test",
                            "retryable": "true"
                          }
                        }
                      ]
                    }
                  }
                }
              }
            }
          }
        },
        "x-noxtica-status": "partial"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/deployments": {
      "post": {
        "operationId": "v1ApmIngestDeploymentMarker",
        "tags": [
          "APM Ingest"
        ],
        "summary": "Ingest a deployment marker",
        "description": "Records one service deployment (a release marker) as a small single-row JSON payload. It is not an OTLP batch, so its request and response shapes are its own rather than the OTLP contract used by traces, metrics, logs and profiles. Only `application/json` is accepted (otherwise `415`), compression is not supported, and the request body is limited to 16 KiB.\n\n`environment` is supplied by the caller but must equal the `environmentId` the ingestion key is bound to: the key's organisation, project and environment decide where a marker lands, and a mismatched value is rejected with `403 apm_environment_mismatch` instead of redirecting the marker. `version` is also the release id.\n\nAuthenticate with an ingestion key (`Authorization: Bearer sk_apm_...`) whose allowed signals include `deployments`.\n\n**Hosts.** Send the request to `https://ingest.noxtica.com` (production): this is the host the Backoffice shows next to an ingestion key. The same path and credential are also served by the collector hosts listed under `servers`.\n\nPer-key and per-project rate limits apply; a limited request answers `429` with a `Retry-After` header. The limit values differ between host implementations and are not part of this contract.",
        "security": [
          {
            "ApmIngestKeyAuth": []
          }
        ],
        "servers": [
          {
            "url": "https://ingest.noxtica.com",
            "description": "Production ingest host"
          },
          {
            "url": "https://collect.noxtica.com",
            "description": "Production collector host (same path and credential)"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ApmDeploymentMarkerRequest"
              },
              "example": {
                "service": "checkout-api",
                "version": "2026.09.25-1",
                "environment": "prod",
                "commit": "4f3c2a1",
                "timestamp": "2026-09-25T00:00:00.000Z"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Deployment marker accepted and queued to the warehouse.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApmDeploymentMarkerAccepted"
                },
                "example": {
                  "ok": true,
                  "deployment_id": "dep-test",
                  "service": "checkout-api",
                  "version": "2026.09.25-1",
                  "environment": "prod",
                  "commit": "4f3c2a1",
                  "timestamp": "2026-09-25T00:00:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`apm_malformed_json` — the body is not valid JSON; or `apm_invalid_payload` — a required field is missing, an unknown field is present, or a field fails its own pattern/format check (e.g. `commit` not a 7-64 char lowercase-hex SHA, or `timestamp` after the receipt time).",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApmDeploymentError"
                },
                "examples": {
                  "malformed_json": {
                    "summary": "Body is not valid JSON.",
                    "value": {
                      "ok": false,
                      "error": "apm_malformed_json",
                      "message": "Malformed JSON body",
                      "requestId": "req-test"
                    }
                  },
                  "invalid_payload": {
                    "summary": "A field failed validation.",
                    "value": {
                      "ok": false,
                      "error": "apm_invalid_payload",
                      "message": "Invalid deployment marker payload",
                      "requestId": "req-test"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid `sk_apm_` bearer credential, or the credential's `effective_at`/`expires_at` window excludes now. A tenant `ApiKeyAuth` `sk_` key is never accepted here.",
            "headers": {
              "WWW-Authenticate": {
                "schema": {
                  "type": "string"
                },
                "description": "On the collector hosts always `Bearer realm=\"noxtica-otlp\", charset=\"UTF-8\"`; the ingest hosts do not send it."
              },
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApmDeploymentError"
                },
                "examples": {
                  "auth_missing": {
                    "summary": "No Authorization header.",
                    "value": {
                      "ok": false,
                      "error": "apm_auth_missing",
                      "message": "Authentication failed",
                      "requestId": "req-test"
                    }
                  },
                  "auth_invalid": {
                    "summary": "Credential does not resolve to an active key.",
                    "value": {
                      "ok": false,
                      "error": "apm_auth_invalid",
                      "message": "Authentication failed",
                      "requestId": "req-test"
                    }
                  },
                  "auth_expired": {
                    "summary": "now is outside [effective_at, expires_at).",
                    "value": {
                      "ok": false,
                      "error": "apm_auth_expired",
                      "message": "Authentication failed",
                      "requestId": "req-test"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "The credential is active but not authorized for deployment marker ingest, or the request's `environment` does not match the credential's own `environmentId` scope.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApmDeploymentError"
                },
                "examples": {
                  "scope_denied": {
                    "summary": "\"deployments\" is not in the credential's allowed_signals.",
                    "value": {
                      "ok": false,
                      "error": "apm_scope_denied",
                      "message": "Deployment marker ingest is not authorized",
                      "requestId": "req-test"
                    }
                  },
                  "purpose_disabled": {
                    "summary": "The credential's purpose_enabled flag is 0.",
                    "value": {
                      "ok": false,
                      "error": "apm_purpose_disabled",
                      "message": "Deployment marker ingest is not authorized",
                      "requestId": "req-test"
                    }
                  },
                  "environment_mismatch": {
                    "summary": "Request environment does not match the credential's own environment scope.",
                    "value": {
                      "ok": false,
                      "error": "apm_environment_mismatch",
                      "message": "environment does not match the authenticated key scope",
                      "requestId": "req-test"
                    }
                  }
                }
              }
            }
          },
          "413": {
            "description": "The request body exceeds the 16 KiB cap.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApmDeploymentError"
                },
                "example": {
                  "ok": false,
                  "error": "apm_body_too_large",
                  "message": "Request body exceeds the deployment marker limit",
                  "requestId": "req-test"
                }
              }
            }
          },
          "415": {
            "description": "Content-Type is not `application/json`.",
            "headers": {
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApmDeploymentError"
                },
                "example": {
                  "ok": false,
                  "error": "apm_unsupported_media_type",
                  "message": "Content-Type must be application/json",
                  "requestId": "req-test"
                }
              }
            }
          },
          "429": {
            "description": "Deployment marker rate limit exceeded (120 requests / 60s per `tenantId:projectId`).",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds until the bucket allows another request."
              },
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApmDeploymentError"
                },
                "example": {
                  "ok": false,
                  "error": "apm_rate_limited",
                  "message": "Deployment marker rate limit exceeded",
                  "requestId": "req-test"
                }
              }
            }
          },
          "503": {
            "description": "The tenant authority scope could not be confirmed, or the durable ingest queue is unavailable.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Always `5` on this status."
              },
              "Cache-Control": {
                "$ref": "#/components/headers/NoStore"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApmDeploymentError"
                },
                "examples": {
                  "authority_unavailable": {
                    "summary": "Tenant authority scope confirmation failed.",
                    "value": {
                      "ok": false,
                      "error": "apm_authority_unavailable",
                      "message": "Authority unavailable",
                      "requestId": "req-test"
                    }
                  },
                  "queue_unavailable": {
                    "summary": "The durable ingest queue binding is missing or rejected the message.",
                    "value": {
                      "ok": false,
                      "error": "apm_queue_unavailable",
                      "message": "Deployment marker queue is unavailable",
                      "requestId": "req-test"
                    }
                  }
                }
              }
            }
          }
        },
        "x-noxtica-status": "partial"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/health": {
      "get": {
        "operationId": "getHealth",
        "tags": [
          "Health and Keys"
        ],
        "summary": "Collector health probe",
        "description": "Unauthenticated liveness and readiness probe of the collector. It performs no datastore\nconnectivity check: it answers whether the collector worker itself is alive.\n\n`status` is `ok`, or `degraded` while a background dead-letter watch reports unprocessed\nitems (still HTTP `200`). HTTP `503` is returned only when the deployment refuses\nreadiness; the body then also has `status: degraded`. The body can carry additional\ndiagnostic members; ignore members you do not recognise. `version` is the deployed\ncollector version, or `unknown` when none is reported.\n\nThe response sets no CORS headers, so call it from a server or a monitor, never from a\nbrowser. Excessive probing from one source address is rate limited (`429` with\n`Retry-After`). For incident history see the public status page.",
        "security": [],
        "responses": {
          "200": {
            "description": "The collector is alive.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-cache"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthStatus"
                },
                "example": {
                  "status": "ok",
                  "version": "1.0.0",
                  "timestamp": "2026-10-27T10:00:00.000Z"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/v1_RateLimited"
          },
          "503": {
            "description": "The deployment refuses readiness. `status` is `degraded`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthStatus"
                },
                "example": {
                  "status": "degraded",
                  "version": "1.0.0",
                  "timestamp": "2026-10-27T10:00:00.000Z"
                }
              }
            }
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/.well-known/noxtica/jwks.json": {
      "get": {
        "operationId": "getCollectorJwks",
        "tags": [
          "Health and Keys"
        ],
        "summary": "Public signing keys (JWKS)",
        "description": "The public keys Noxtica signs its envelopes with, as a standard JSON Web Key Set, so your\nbackend can verify a signed envelope offline, by `kid`, without calling Noxtica: the signed\npolicy and result envelopes of the browser integration and, unless a dedicated passport key\nis published (see `GET /.well-known/noxtica/agent-passport-jwks.json`), Agent Passports.\n\nThe document is unauthenticated and public by design: only the public members `kty`,\n`crv`, `x`, `y` and the descriptors `kid`, `use` and `alg` are ever served. During a key\nrotation it holds both the current and the incoming key (current first), so a verifier can\nresolve the new `kid` before the signer cuts over. The response is cacheable for 5 minutes.\nThe route answers `404` when signing is not configured for the deployment.",
        "security": [],
        "responses": {
          "200": {
            "description": "The public key set.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "public, max-age=300"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Jwks"
                },
                "example": {
                  "keys": [
                    {
                      "kty": "EC",
                      "crv": "P-256",
                      "x": "f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU",
                      "y": "x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0",
                      "kid": "nox-2026-01",
                      "use": "sig",
                      "alg": "ES256"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Signing is not configured for this deployment. The body is `{\"error\":\"Not found\"}`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                },
                "example": {
                  "error": "Not found"
                }
              }
            }
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/.well-known/noxtica/agent-passport-jwks.json": {
      "get": {
        "operationId": "getAgentPassportJwks",
        "tags": [
          "Health and Keys"
        ],
        "summary": "Public Agent Passport signing keys (JWKS)",
        "description": "The public key of the dedicated Agent Passport signing key, when one is provisioned, as a\nstandard JSON Web Key Set. It is deliberately a separate document from\n`GET /.well-known/noxtica/jwks.json` so a result verifier that fetches only the main\ndocument can never accept a passport. Use this document, and only for Agent Passports.\n\nThe route answers `404` when no dedicated passport key exists; passports are then signed\nunder a key published on the main JWKS. During a rotation both the current and the\nincoming key are published (current first). The document is unauthenticated, public by\ndesign and cacheable for 5 minutes.",
        "security": [],
        "responses": {
          "200": {
            "description": "The public key set of the dedicated passport signing key.",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "public, max-age=300"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Jwks"
                },
                "example": {
                  "keys": [
                    {
                      "kty": "EC",
                      "crv": "P-256",
                      "x": "f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU",
                      "y": "x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0",
                      "kid": "nox-passport-2026-01",
                      "use": "sig",
                      "alg": "ES256"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "No dedicated passport key is configured. The body is `{\"error\":\"Not found\"}`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NotFoundError"
                },
                "example": {
                  "error": "Not found"
                }
              }
            }
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/coding-agent/findings": {
      "get": {
        "operationId": "codingAgentListFindings",
        "tags": [
          "Coding Agent"
        ],
        "summary": "List recent findings for a coding agent",
        "description": "Reads recent raw signals for your organisation, narrowed to the scopes the coding-agent key\nholds. Results from every scope the key holds are merged: this route has no single required\nscope, and a scope narrows what is read instead of denying the call. At the time of writing\nthe scopes `rum_errors`, `apm_traces`, `apm_errors`, `apm_metrics` and `logs` have a findings\nsource; the other scopes a key can carry (`profiles`, `fingerprint_bot_signals`,\n`kyc_risk_summaries`) add nothing to this route. The `signal` field names the scope a row\ncame from. An empty array is a normal answer; this route never answers `404`.\n\n`since` defaults to 24 hours ago and `limit` to 50 (maximum 200). Create a coding-agent\nkey in the Backoffice under Integrations & API, Coding agent keys; keys start with `cak_`.",
        "security": [
          {
            "CodingAgentKeyAuth": []
          }
        ],
        "servers": [
          {
            "url": "https://ingest.noxtica.com",
            "description": "Production"
          }
        ],
        "parameters": [
          {
            "name": "since",
            "in": "query",
            "required": false,
            "description": "Only signals observed at or after this RFC 3339 instant. Defaults to 24 hours ago.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of signals to return. Defaults to 50; values above 200 are clamped to 200.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A (possibly empty) array of signals.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/CodingAgentSignal"
                  }
                },
                "example": [
                  {
                    "signal": "rum_errors",
                    "reference_id": "evt_8f1c2a",
                    "excerpt": "error /checkout",
                    "observed_at": "2026-10-27T09:58:12Z"
                  }
                ]
              }
            }
          },
          "400": {
            "description": "`schema_invalid` — `since` or `limit` could not be parsed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CodingAgentError"
                },
                "example": {
                  "code": 400,
                  "message": "invalid query",
                  "error": "schema_invalid"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/CodingAgentUnauthorized"
          },
          "429": {
            "$ref": "#/components/responses/CodingAgentRateLimited"
          },
          "502": {
            "$ref": "#/components/responses/CodingAgentQueryFailed"
          },
          "503": {
            "$ref": "#/components/responses/CodingAgentUnavailable"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/coding-agent/traces/{trace_id}": {
      "get": {
        "operationId": "codingAgentGetTrace",
        "tags": [
          "Coding Agent"
        ],
        "summary": "Read one trace for a coding agent",
        "description": "Returns the spans of one trace (a narrow projection: attributes, events and links are never\nreturned) from roughly the last 30 days. Requires the `apm_traces` scope on the key;\nwithout it the route answers `403 coding_agent_scope_denied`. An unknown trace id, or one\nthat belongs to another organisation, is a normal `200` with an empty `spans` array: this\nroute never answers `404`.",
        "security": [
          {
            "CodingAgentKeyAuth": []
          }
        ],
        "servers": [
          {
            "url": "https://ingest.noxtica.com",
            "description": "Production"
          }
        ],
        "parameters": [
          {
            "name": "trace_id",
            "in": "path",
            "required": true,
            "description": "The trace id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The trace; `spans` is empty when the id is unknown.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CodingAgentTrace"
                },
                "example": {
                  "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
                  "spans": [
                    {
                      "span_id": "00f067aa0ba902b7",
                      "service_name": "checkout-api",
                      "operation_name": "GET /health",
                      "start_time": "2026-10-27T09:58:00Z",
                      "end_time": "2026-10-27T09:58:00.010Z",
                      "duration_ns": 10000000,
                      "status_code": "STATUS_CODE_OK"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/CodingAgentUnauthorized"
          },
          "403": {
            "$ref": "#/components/responses/CodingAgentScopeDenied"
          },
          "429": {
            "$ref": "#/components/responses/CodingAgentRateLimited"
          },
          "502": {
            "$ref": "#/components/responses/CodingAgentQueryFailed"
          },
          "503": {
            "$ref": "#/components/responses/CodingAgentUnavailable"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    },
    "/v1/coding-agent/errors/{error_group_id}": {
      "get": {
        "operationId": "codingAgentGetErrorGroup",
        "tags": [
          "Coding Agent"
        ],
        "summary": "Read one error group for a coding agent",
        "description": "Returns one error group with its aggregate counts and a bounded list of recent occurrences\n(a narrow projection: stack frames are never returned) from roughly the last 30 days.\nRequires the `apm_errors` scope on the key; without it the route answers\n`403 coding_agent_scope_denied`. `404 coding_agent_error_group_not_found` means the group is\nunknown or belongs to another organisation; the two cases are indistinguishable by design.",
        "security": [
          {
            "CodingAgentKeyAuth": []
          }
        ],
        "servers": [
          {
            "url": "https://ingest.noxtica.com",
            "description": "Production"
          }
        ],
        "parameters": [
          {
            "name": "error_group_id",
            "in": "path",
            "required": true,
            "description": "The error group id.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The error group.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CodingAgentErrorGroup"
                },
                "example": {
                  "error_group_id": "eg_5d41402abc4b2a76",
                  "first_seen": "2026-10-26T08:00:00Z",
                  "last_seen": "2026-10-27T09:58:12Z",
                  "occurrence_count": 42,
                  "affected_release_ids": [
                    "2026.10.26"
                  ],
                  "occurrences": [
                    {
                      "occurrence_id": "occ_91",
                      "exception_type": "TypeError",
                      "exception_message": "Cannot read properties of undefined",
                      "observed_at": "2026-10-27T09:58:12Z",
                      "release_id": "2026.10.26"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/CodingAgentUnauthorized"
          },
          "403": {
            "$ref": "#/components/responses/CodingAgentScopeDenied"
          },
          "404": {
            "description": "`coding_agent_error_group_not_found` — the group is unknown or belongs to another organisation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CodingAgentError"
                },
                "example": {
                  "code": 404,
                  "message": "Unknown error group",
                  "error": "coding_agent_error_group_not_found"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/CodingAgentRateLimited"
          },
          "502": {
            "$ref": "#/components/responses/CodingAgentQueryFailed"
          },
          "503": {
            "$ref": "#/components/responses/CodingAgentUnavailable"
          }
        },
        "x-noxtica-status": "available"
      },
      "servers": [
        {
          "url": "https://collect.noxtica.com",
          "description": "Production",
          "x-noxtica-key-prefix": "sk_prod_"
        }
      ]
    }
  },
  "webhooks": {
    "kyc.session.completed": {
      "post": {
        "operationId": "kycWebhookSessionCompleted",
        "tags": [
          "KYC Webhooks"
        ],
        "summary": "A hosted verification session reached a business outcome",
        "description": "Sent by Noxtica to every endpoint you registered for `kyc.session.completed`\n(Backoffice, Integrations & API, Webhooks). See \"Webhooks (KYC)\" in the API description\nfor the headers, the signature, retries and deduplication; they are common to all six\nKYC events.\n\n**When it fires.** A hosted session reached `completed`, `unverified` or `error`.\n**It does not fire when a session lands in `review_pending`.** With the identity provider\nconfigured today, a successful hosted capture ends in `review_pending` (the provider\nroutes every success to manual review, reason code `provider_manual_review`); the event\nis sent later, when a Backoffice reviewer approves or overrides the case and the session\nmoves `review_pending` to `completed`. Allow up to about 5 minutes between the reviewer's\ndecision and the delivery (the relay runs on the platform's 5-minute tick). A\n`review_pending` session never expires, so your system must keep waiting for the\ndecision (or poll `GET /v1/kyc/sessions/{sessionId}`). It never fires for `expired`\nor `cancelled_by_user` sessions.\n\nThis is a notification, not authority: before you act on it, read\n`GET /v1/kyc/sessions/{sessionId}`. The payload carries no subject reference; correlate\nby `data.sessionId`, the id you stored when you minted the session.",
        "security": [],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookSignatureHeader"
          },
          {
            "$ref": "#/components/parameters/WebhookTimestampHeader"
          },
          {
            "$ref": "#/components/parameters/WebhookEventHeader"
          },
          {
            "$ref": "#/components/parameters/WebhookDeliveryHeader"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/KycSessionCompletedWebhookEvent"
              },
              "example": {
                "id": "6d3c3a8e-6b4b-4a8f-8f4e-0a0e6b3d9d21:wh_7f3a2c",
                "type": "kyc.session.completed",
                "created_at": 1790762445000,
                "tenant_id": "tenant_42",
                "data": {
                  "schemaVersion": "1",
                  "sessionId": "6d3c3a8e-6b4b-4a8f-8f4e-0a0e6b3d9d21",
                  "status": "completed",
                  "verificationId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                  "reasonCodes": [],
                  "occurredAt": 1790762445000,
                  "deliveryId": "6d3c3a8e-6b4b-4a8f-8f4e-0a0e6b3d9d21:wh_7f3a2c"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Acknowledge with any 2xx status. See \"Webhooks (KYC)\" for how other statuses are treated."
          }
        }
      }
    },
    "kyc.session.cancelled": {
      "post": {
        "operationId": "kycWebhookSessionCancelled",
        "tags": [
          "KYC Webhooks"
        ],
        "summary": "The end customer cancelled a hosted verification session",
        "description": "Sent when the customer confirms on the hosted page that they do not want to continue and\nthe session actually moves to `cancelled_by_user`. Available only when session\ncancellation is enabled for your organisation. Subscriptions are opt-in per event: an\nendpoint registered before this event existed does not receive it until you add it to the\nendpoint's event list.\n\n`data.cancelReason` and `data.cancelledAt` are delivered only in this event.\n`GET /v1/kyc/sessions/{sessionId}` reports the terminal status `cancelled_by_user` but does\nnot return the cancel reason or the cancel time. An expiry emits no event; observe it by\nreading the session status.\n\nSee \"Webhooks (KYC)\" in the API description for headers, signature, retries and\ndeduplication.",
        "security": [],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookSignatureHeader"
          },
          {
            "$ref": "#/components/parameters/WebhookTimestampHeader"
          },
          {
            "$ref": "#/components/parameters/WebhookEventHeader"
          },
          {
            "$ref": "#/components/parameters/WebhookDeliveryHeader"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/KycSessionCancelledWebhookEvent"
              },
              "example": {
                "id": "6d3c3a8e-6b4b-4a8f-8f4e-0a0e6b3d9d21:wh_7f3a2c",
                "type": "kyc.session.cancelled",
                "created_at": 1790762300000,
                "tenant_id": "tenant_42",
                "data": {
                  "schemaVersion": "1",
                  "sessionId": "6d3c3a8e-6b4b-4a8f-8f4e-0a0e6b3d9d21",
                  "status": "cancelled_by_user",
                  "cancelReason": "not_now",
                  "cancelledAt": 1790762300000,
                  "occurredAt": 1790762300000,
                  "deliveryId": "6d3c3a8e-6b4b-4a8f-8f4e-0a0e6b3d9d21:wh_7f3a2c"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Acknowledge with any 2xx status. See \"Webhooks (KYC)\" for how other statuses are treated."
          }
        }
      }
    },
    "kyc.verification.completed": {
      "post": {
        "operationId": "kycWebhookVerificationCompleted",
        "tags": [
          "KYC Webhooks"
        ],
        "summary": "A KYC verification request reached a terminal state",
        "description": "Sent when a verification request (`POST /v1/kyc/verify`, or the verification a hosted\nsession runs when the customer submits) reaches a terminal state: `completed`,\n`terminal_error`, `expired` or `cancelled`. The non-terminal states `retryable_error`\nand `provider_unknown` emit nothing. `data.verdict` is the stored canonical verdict\n(`verified`, `unverified` or `error`; `error` for an infrastructure-faulted terminal\nrequest that has no verdict).\n\nA hosted session's submit runs the same pipeline, so an endpoint subscribed to both events\ncan receive `kyc.verification.completed` for the same attempt as\n`kyc.session.*`; with the identity provider configured today the verdict of a successful\nhosted capture is `unverified` with the reason code `provider_manual_review`. Delivery\norder between the two events is not guaranteed. `data.verificationId` equals\n`session.verificationId` on the session status read.\n\nSee \"Webhooks (KYC)\" in the API description for headers, signature, retries and\ndeduplication.",
        "security": [],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookSignatureHeader"
          },
          {
            "$ref": "#/components/parameters/WebhookTimestampHeader"
          },
          {
            "$ref": "#/components/parameters/WebhookEventHeader"
          },
          {
            "$ref": "#/components/parameters/WebhookDeliveryHeader"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/KycVerificationCompletedWebhookEvent"
              },
              "example": {
                "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6:wh_7f3a2c",
                "type": "kyc.verification.completed",
                "created_at": 1790762440000,
                "tenant_id": "tenant_42",
                "data": {
                  "schemaVersion": "1",
                  "verificationId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                  "verdict": "unverified",
                  "reasonCodes": [
                    "provider_manual_review"
                  ],
                  "idType": "passport",
                  "occurredAt": 1790762440000,
                  "deliveryId": "3fa85f64-5717-4562-b3fc-2c963f66afa6:wh_7f3a2c"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Acknowledge with any 2xx status. See \"Webhooks (KYC)\" for how other statuses are treated."
          }
        }
      }
    },
    "kyc.erasure.completed": {
      "post": {
        "operationId": "kycWebhookErasureCompleted",
        "tags": [
          "KYC Webhooks"
        ],
        "summary": "A KYC erasure request finished successfully",
        "description": "Sent when an erasure request reaches `completed`. A `partial` erasure never emits this\nevent. The payload deliberately carries no subject identifier or subject digest: an erasure\nnotification must not re-establish a link to the person whose linkage was just erased.\n`data.requestId` is the erasure request's own id.\n\nSee \"Webhooks (KYC)\" in the API description for headers, signature, retries and\ndeduplication.",
        "security": [],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookSignatureHeader"
          },
          {
            "$ref": "#/components/parameters/WebhookTimestampHeader"
          },
          {
            "$ref": "#/components/parameters/WebhookEventHeader"
          },
          {
            "$ref": "#/components/parameters/WebhookDeliveryHeader"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/KycErasureCompletedWebhookEvent"
              },
              "example": {
                "id": "er_4b81d2:wh_7f3a2c",
                "type": "kyc.erasure.completed",
                "created_at": 1790900000000,
                "tenant_id": "tenant_42",
                "data": {
                  "schemaVersion": "1",
                  "requestId": "er_4b81d2",
                  "outcome": "completed",
                  "occurredAt": 1790900000000,
                  "deliveryId": "er_4b81d2:wh_7f3a2c"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Acknowledge with any 2xx status. See \"Webhooks (KYC)\" for how other statuses are treated."
          }
        }
      }
    },
    "kyc.document.expiry_warning": {
      "post": {
        "operationId": "kycWebhookDocumentExpiryWarning",
        "tags": [
          "KYC Webhooks"
        ],
        "summary": "A verified identity document is approaching or past its expiry",
        "description": "Sent by the scheduled document-expiry monitoring pass when a monitored verification's\ndocument crosses the 90, 60 or 30 day threshold or has expired (`data.alertType`). Only\navailable when document-expiry monitoring is enabled for your organisation. Each\nthreshold fires once per monitored verification.\n\nUnlike the other KYC events, this event is not read from the delivery ledger: the\nscheduled pass makes a single signed delivery attempt to each subscribed endpoint and\ndoes not retry a failed attempt. Deduplicate on the delivery id anyway, and use\n`data.verificationId` to correlate with the original `kyc.verification.completed`.\nSee \"Webhooks (KYC)\" for headers and signature.",
        "security": [],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookSignatureHeader"
          },
          {
            "$ref": "#/components/parameters/WebhookTimestampHeader"
          },
          {
            "$ref": "#/components/parameters/WebhookEventHeader"
          },
          {
            "$ref": "#/components/parameters/WebhookDeliveryHeader"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/KycDocumentExpiryWarningWebhookEvent"
              },
              "example": {
                "id": "sched_91c0:wh_7f3a2c",
                "type": "kyc.document.expiry_warning",
                "created_at": 1798538000000,
                "tenant_id": "tenant_42",
                "data": {
                  "schemaVersion": "1",
                  "verificationId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                  "alertType": "expiry_30d",
                  "documentExpiresAt": 1801130000000,
                  "occurredAt": 1798538000000,
                  "deliveryId": "sched_91c0:wh_7f3a2c"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Acknowledge with any 2xx status. See \"Webhooks (KYC)\" for how other statuses are treated."
          }
        }
      }
    },
    "kyc.reverification.due": {
      "post": {
        "operationId": "kycWebhookReverificationDue",
        "tags": [
          "KYC Webhooks"
        ],
        "summary": "A previously verified identity is due for re-verification",
        "description": "Sent by the same scheduled monitoring pass as `kyc.document.expiry_warning` when a\nre-verification schedule entry reaches its due time. Only available when document-expiry\nmonitoring is enabled for your organisation, and only for a verification that has a\nre-verification schedule entry. Single signed delivery attempt, no retry, as for\n`kyc.document.expiry_warning`.\n\nSee \"Webhooks (KYC)\" in the API description for headers and signature.",
        "security": [],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookSignatureHeader"
          },
          {
            "$ref": "#/components/parameters/WebhookTimestampHeader"
          },
          {
            "$ref": "#/components/parameters/WebhookEventHeader"
          },
          {
            "$ref": "#/components/parameters/WebhookDeliveryHeader"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/KycReverificationDueWebhookEvent"
              },
              "example": {
                "id": "sched_92d1:wh_7f3a2c",
                "type": "kyc.reverification.due",
                "created_at": 1801130000000,
                "tenant_id": "tenant_42",
                "data": {
                  "schemaVersion": "1",
                  "verificationId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                  "dueAt": 1801130000000,
                  "occurredAt": 1801130000000,
                  "deliveryId": "sched_92d1:wh_7f3a2c"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Acknowledge with any 2xx status. See \"Webhooks (KYC)\" for how other statuses are treated."
          }
        }
      }
    },
    "submission.scored": {
      "post": {
        "operationId": "webhookSubmissionScored",
        "tags": [
          "Verdict Webhooks"
        ],
        "summary": "A submission was scored",
        "description": "Sent for every scored browser or app submission of your organisation (the broadest\nsubscription: use `risk.high` or `risk.flagged` if you only need the notable ones). The\nBackoffice \"Send test\" button sends a sample of this event type, with placeholder verdict\ndata and a valid signature.\n\n`data.event_id` is the request id of the submission: correlate it with the `X-Request-Id`\nyour browser integration received. `data.device_id` is the opaque device id\n(`fingerprintId`). This is a notification, not authority; read the device\n(`GET /v1/device/{deviceId}`) before taking an irreversible action.\n\nSee \"Webhook delivery and retries\" in the API description for the headers, the signature,\nretries and deduplication.",
        "security": [],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookSignatureHeader"
          },
          {
            "$ref": "#/components/parameters/WebhookTimestampHeader"
          },
          {
            "$ref": "#/components/parameters/v1_WebhookEventHeader"
          },
          {
            "$ref": "#/components/parameters/v1_WebhookDeliveryHeader"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VerdictWebhookEvent"
              },
              "example": {
                "id": "6d3c3a8e-6b4b-4a8f-8f4e-0a0e6b3d9d21",
                "type": "submission.scored",
                "created_at": 1790762445000,
                "tenant_id": "YOUR_TENANT_ID",
                "data": {
                  "score": 12,
                  "risk_level": "low",
                  "confidence": 0.91,
                  "flags": [],
                  "reason_codes": [],
                  "device_id": "a1b2c3d4e5f60718293a4b5c6d7e8f90",
                  "domain_id": "dom_42",
                  "event_id": "8f1c2a52-6a6e-4b0e-9d52-2a7c1d9e4b10"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Acknowledge with any 2xx status. See \"Webhook delivery and retries\" for how other statuses are treated."
          }
        },
        "x-noxtica-status": "available"
      }
    },
    "risk.high": {
      "post": {
        "operationId": "webhookRiskHigh",
        "tags": [
          "Verdict Webhooks"
        ],
        "summary": "A submission was scored high or critical",
        "description": "Sent when a scored submission lands in the `high` or `critical` risk band. The payload is\nthe same verdict shape as `submission.scored`. A submission in that band also produces\n`submission.scored` (and `risk.flagged` when a flag fired) for endpoints subscribed to\nthose types.\n\nSee \"Webhook delivery and retries\" in the API description for the headers, the signature,\nretries and deduplication.",
        "security": [],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookSignatureHeader"
          },
          {
            "$ref": "#/components/parameters/WebhookTimestampHeader"
          },
          {
            "$ref": "#/components/parameters/v1_WebhookEventHeader"
          },
          {
            "$ref": "#/components/parameters/v1_WebhookDeliveryHeader"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VerdictWebhookEvent"
              },
              "example": {
                "id": "0b9d7b1c-2f0e-4c8b-9a52-7c1b3a1f9e11",
                "type": "risk.high",
                "created_at": 1790762446000,
                "tenant_id": "YOUR_TENANT_ID",
                "data": {
                  "score": 87,
                  "risk_level": "high",
                  "confidence": 0.88,
                  "flags": [
                    "example_flag"
                  ],
                  "reason_codes": [],
                  "device_id": "a1b2c3d4e5f60718293a4b5c6d7e8f90",
                  "domain_id": "dom_42",
                  "event_id": "3a7d1e52-6a6e-4b0e-9d52-2a7c1d9e4b11"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Acknowledge with any 2xx status. See \"Webhook delivery and retries\" for how other statuses are treated."
          }
        },
        "x-noxtica-status": "available"
      }
    },
    "risk.flagged": {
      "post": {
        "operationId": "webhookRiskFlagged",
        "tags": [
          "Verdict Webhooks"
        ],
        "summary": "A risk flag fired",
        "description": "Sent when at least one risk flag fired on a scored submission, whatever its risk band.\n\nThe same event type is also sent after each mobile attestation `verify` (see\n`POST /v1/attest/android` and `POST /v1/attest/ios`), with `flags` of the form\n`mobile_attest:<platform>`, `mobile_attest_level:<level>` and `mobile_attest_verdict:<verdict>`.\nThere `data.device_id` can be an empty string, which means that no stable per-device\nidentity is available for the event: do not group events on an empty `device_id`, and use\n`data.event_id`, which is always present, as the per-event key.\n\nSee \"Webhook delivery and retries\" in the API description for the headers, the signature,\nretries and deduplication.",
        "security": [],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookSignatureHeader"
          },
          {
            "$ref": "#/components/parameters/WebhookTimestampHeader"
          },
          {
            "$ref": "#/components/parameters/v1_WebhookEventHeader"
          },
          {
            "$ref": "#/components/parameters/v1_WebhookDeliveryHeader"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VerdictWebhookEvent"
              },
              "example": {
                "id": "9c1e5d2a-3b4f-4a6c-8d7e-1f2a3b4c5d6e",
                "type": "risk.flagged",
                "created_at": 1790762447000,
                "tenant_id": "YOUR_TENANT_ID",
                "data": {
                  "score": 40,
                  "risk_level": "medium",
                  "confidence": 0.7,
                  "flags": [
                    "example_flag"
                  ],
                  "reason_codes": [],
                  "device_id": "a1b2c3d4e5f60718293a4b5c6d7e8f90",
                  "domain_id": "dom_42",
                  "event_id": "5e8f2a52-6a6e-4b0e-9d52-2a7c1d9e4b12"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Acknowledge with any 2xx status. See \"Webhook delivery and retries\" for how other statuses are treated."
          }
        },
        "x-noxtica-status": "available"
      }
    },
    "risk.cluster_flagged": {
      "post": {
        "operationId": "webhookRiskClusterFlagged",
        "tags": [
          "Verdict Webhooks"
        ],
        "summary": "A device cluster was flagged as bad",
        "description": "Sent once, on the first escalation, when a cluster of devices (devices sharing an\nobservational sub-fingerprint) is flagged bad in real time because a high or critical\nsubmission came with strong cluster evidence. It lets you react to an emerging cluster\nbefore slower offline feeds catch up. A cluster that is already flagged does not produce\na new delivery for every further submission.\n\nThe payload has the same verdict shape as `submission.scored`; `data.risk_level` is the\ncluster's band. It carries no raw IP address and no personal data. Available only when\nreal-time cluster propagation is enabled for the deployment.\n\nSee \"Webhook delivery and retries\" in the API description for the headers, the signature,\nretries and deduplication.",
        "security": [],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookSignatureHeader"
          },
          {
            "$ref": "#/components/parameters/WebhookTimestampHeader"
          },
          {
            "$ref": "#/components/parameters/v1_WebhookEventHeader"
          },
          {
            "$ref": "#/components/parameters/v1_WebhookDeliveryHeader"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VerdictWebhookEvent"
              },
              "example": {
                "id": "2a4c6e8f-1b3d-4f5a-9c7e-0d2b4f6a8c1e",
                "type": "risk.cluster_flagged",
                "created_at": 1790762448000,
                "tenant_id": "YOUR_TENANT_ID",
                "data": {
                  "score": 91,
                  "risk_level": "critical",
                  "confidence": 0.93,
                  "flags": [
                    "example_flag"
                  ],
                  "reason_codes": [],
                  "device_id": "a1b2c3d4e5f60718293a4b5c6d7e8f90",
                  "domain_id": "dom_42",
                  "event_id": "7a9b1c52-6a6e-4b0e-9d52-2a7c1d9e4b13"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Acknowledge with any 2xx status. See \"Webhook delivery and retries\" for how other statuses are treated."
          }
        },
        "x-noxtica-status": "available"
      }
    },
    "account.agent_linked": {
      "post": {
        "operationId": "webhookAccountAgentLinked",
        "tags": [
          "Verdict Webhooks"
        ],
        "summary": "A verified agent was linked to an account for the first time",
        "description": "Sent once, when a cryptographically verified signed agent (Web Bot Auth, RFC 9421) is linked\nto one of your end-user accounts for the first time, that is when the (agent, account)\npair had no earlier link. It lets you react when a new agent starts acting on an account.\n\nThe payload carries the keyed `account_hash` (a 16-character lowercase-hex pseudonym; the\nraw account id is never stored or sent), the verified agent's `agent_keyid` and\n`agent_host`, and the usual `device_id`, `domain_id` and `event_id`. It carries no raw IP\naddress and no personal data. Use `GET /v1/accounts/{accountHash}/devices` to list the\ndevices and agents linked to the account.\n\nSee \"Webhook delivery and retries\" in the API description for the headers, the signature,\nretries and deduplication.",
        "security": [],
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookSignatureHeader"
          },
          {
            "$ref": "#/components/parameters/WebhookTimestampHeader"
          },
          {
            "$ref": "#/components/parameters/v1_WebhookEventHeader"
          },
          {
            "$ref": "#/components/parameters/v1_WebhookDeliveryHeader"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AgentLinkedWebhookEvent"
              },
              "example": {
                "id": "4d6f8a1c-5e7b-4d9f-8a2c-3b5d7f9a1c2e",
                "type": "account.agent_linked",
                "created_at": 1790762449000,
                "tenant_id": "YOUR_TENANT_ID",
                "data": {
                  "account_hash": "0a1b2c3d4e5f6071",
                  "agent_keyid": "agent-key-1",
                  "agent_host": "agent.example.com",
                  "device_id": "a1b2c3d4e5f60718293a4b5c6d7e8f90",
                  "domain_id": "dom_42",
                  "event_id": "9b1d3f52-6a6e-4b0e-9d52-2a7c1d9e4b14"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Acknowledge with any 2xx status. See \"Webhook delivery and retries\" for how other statuses are treated."
          }
        },
        "x-noxtica-status": "available"
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "sk_<random>",
        "description": "Server-to-server tenant API key. Header: `Authorization: Bearer sk_...`. Scopes are self-mintable per tenant; the scope required by each operation is listed in that operation's `security` block. Recognized KYC/KYB/KYM scopes: `write:identity` (verify, batch, reverify, evidence, sessions, erasure and activate — all share this one scope, there is no separate `read:identity`), `write:kym` (KYM transactions)."
      },
      "SessionTokenAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "kycs.<tenant>.<secret>",
        "description": "Opaque hosted-session bearer token, minted once by the matching `POST .../sessions` S2S call and never re-issued. The tenant id rides inside the token itself. Additionally origin-enforced against the tenant's `ALLOWED_ORIGINS` allowlist — a missing or disallowed `Origin` header refuses with `403 origin_not_allowed` even given a valid token."
      },
      "McpTokenAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "mcp_<random>",
        "description": "MCP token (`Authorization: Bearer mcp_...`) created under Integrations & API, MCP tokens. A static opaque bearer token, not OAuth. It is accepted only by this endpoint."
      },
      "tenantKey": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "sk_prod_<32 hex>",
        "description": "The platform's tenant API key (minted in the Backoffice; scopes `read:pulse`, `write:pulse`), for the tenant's own back-end on `/pulse/v1/tenant/*` only. Looked up through an HMAC hash; a device token or a web session is refused.",
        "x-noxtica-scopes": {
          "read:pulse": "Read subject status and links.",
          "write:pulse": "Issue link codes, unlink and reverse decisions."
        }
      },
      "v1_ApiKeyAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "sk_<random>",
        "description": "Server-to-server tenant API key, sent as `Authorization: Bearer sk_...` (`sk_prod_...` keys). Keys carry scopes: the scope an operation requires is listed in its `security` block, and a valid key without it receives `403`. A missing, malformed, unknown or revoked key, or a key of a suspended organisation, receives a `401` whose body is identical for every cause. Create and revoke keys in the Backoffice under Integrations & API. Use a key only from your own servers — never from a browser or a mobile app."
      },
      "ApmIngestKeyAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "sk_apm_<random>",
        "description": "Dedicated ingestion key (`sk_apm_...`, matching `^sk_apm_[A-Za-z0-9_-]{24,256}$`), created per project and environment under Integrations & API → Ingestion API keys. It carries an allowlist of signals chosen at creation and is the ONLY credential the ingestion operations accept: a server API key (`sk_...`), however broad its scopes, is rejected there, and an `sk_apm_` key is rejected on every other route."
      },
      "CodingAgentKeyAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "cak_<random>",
        "description": "Coding-agent read key (`Authorization: Bearer cak_...`, matching `^cak_[A-Za-z0-9_-]{24,256}$`), created under Integrations & API → Coding agent keys with a chosen set of scopes. It is accepted only by the coding-agent read operations, on the ingestion hosts; a server API key (`sk_...`) or an ingestion key (`sk_apm_...`) is rejected there."
      }
    },
    "parameters": {
      "IdempotencyKeyRequired": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": true,
        "schema": {
          "type": "string",
          "minLength": 8,
          "maxLength": 128
        },
        "description": "A replayed key returns the byte-identical stored response — no second provider call, no double charge."
      },
      "IdempotencyKeyOptional": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": false,
        "schema": {
          "type": "string",
          "minLength": 8,
          "maxLength": 128
        },
        "description": "When supplied, a replayed key returns the SAME minted session (WITHOUT re-exposing its one-shot URL) instead of a fresh mint. Omit entirely for a plain, always-fresh mint."
      },
      "WebhookSignatureHeader": {
        "name": "X-Noxtica-Signature",
        "in": "header",
        "required": true,
        "description": "`sha256=` followed by the lowercase hex HMAC-SHA256 of the string `<X-Noxtica-Timestamp>.<raw request body>`, keyed with the endpoint's signing secret (the secret string's UTF-8 bytes). Verify against the raw body bytes before parsing, with a constant-time comparison.",
        "schema": {
          "type": "string",
          "pattern": "^sha256=[0-9a-f]{64}$",
          "example": "sha256=9f2c4b7e1a8d3c6f0b5e7a9d2c4f6e8b1a3d5c7e9f0b2d4f6a8c0e1b3d5f7a9c"
        }
      },
      "WebhookTimestampHeader": {
        "name": "X-Noxtica-Timestamp",
        "in": "header",
        "required": true,
        "description": "Unix time in milliseconds at which this attempt was signed. Every retry is re-signed with a fresh timestamp, so compare it with your own clock (a 300 second tolerance is recommended; Noxtica itself enforces none), not with the body's `created_at`.",
        "schema": {
          "type": "integer",
          "format": "int64",
          "example": 1790762445123
        }
      },
      "WebhookEventHeader": {
        "name": "X-Noxtica-Event",
        "in": "header",
        "required": true,
        "description": "The event type; equals `type` in the body.",
        "schema": {
          "type": "string",
          "example": "kyc.session.completed"
        }
      },
      "WebhookDeliveryHeader": {
        "name": "X-Noxtica-Delivery",
        "in": "header",
        "required": true,
        "description": "The delivery id; equals `id` in the body and `data.deliveryId`. It is identical on every retry of the same delivery: use it as the deduplication key.",
        "schema": {
          "type": "string",
          "example": "6d3c3a8e-6b4b-4a8f-8f4e-0a0e6b3d9d21:wh_7f3a2c"
        }
      },
      "TenantAppId": {
        "name": "appId",
        "in": "query",
        "required": false,
        "description": "Narrows an `externalUserId` that is linked in several applications of the tenant (else `409 ambiguous_subject`).",
        "schema": {
          "type": "string",
          "pattern": "^[A-Za-z0-9_.:-]{1,64}$"
        }
      },
      "TenantLinkSubject": {
        "name": "subject",
        "in": "path",
        "required": true,
        "description": "The pairwise `plnk_…` subject or the tenant's own `externalUserId` (1..256 characters, percent-encoded).",
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 256
        },
        "example": "plnk_01M4GW6CR553W8AAWXEG17RDJW"
      },
      "ApmListLimit": {
        "name": "limit",
        "in": "query",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 200,
          "default": 50
        }
      },
      "ApmQueryLimit": {
        "name": "limit",
        "in": "query",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 200,
          "default": 50
        }
      },
      "ApmCursor": {
        "name": "cursor",
        "in": "query",
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 512
        }
      },
      "ApmProjectIdPath": {
        "name": "projectId",
        "in": "path",
        "required": true,
        "schema": {
          "$ref": "#/components/schemas/ApmScopedId"
        }
      },
      "ApmEnvironmentIdPath": {
        "name": "environmentId",
        "in": "path",
        "required": true,
        "schema": {
          "$ref": "#/components/schemas/ApmScopedId"
        }
      },
      "ApmProjectIdQuery": {
        "name": "project_id",
        "in": "query",
        "required": true,
        "schema": {
          "$ref": "#/components/schemas/ApmScopedId"
        }
      },
      "ApmEnvironmentIdQuery": {
        "name": "environment_id",
        "in": "query",
        "required": true,
        "schema": {
          "$ref": "#/components/schemas/ApmScopedId"
        }
      },
      "ApmFrom": {
        "name": "from",
        "in": "query",
        "required": true,
        "description": "Inclusive RFC 3339 range start. The interval to `to` must not exceed 31 days.",
        "schema": {
          "type": "string",
          "format": "date-time"
        }
      },
      "ApmTo": {
        "name": "to",
        "in": "query",
        "required": true,
        "description": "Exclusive RFC 3339 range end, after `from`; the interval must not exceed 31 days.",
        "schema": {
          "type": "string",
          "format": "date-time"
        }
      },
      "ApmTraceIdPath": {
        "name": "traceId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "pattern": "^(?!0{32}$)[0-9a-f]{32}$"
        }
      },
      "ApmServiceNamePath": {
        "name": "serviceName",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 256,
          "pattern": "^[A-Za-z0-9._:/-]+$"
        }
      },
      "ApmReleaseIdPath": {
        "name": "releaseId",
        "in": "path",
        "required": true,
        "schema": {
          "$ref": "#/components/schemas/ApmScopedId"
        }
      },
      "ApmExportIdPath": {
        "name": "exportId",
        "in": "path",
        "required": true,
        "schema": {
          "$ref": "#/components/schemas/ApmScopedId"
        }
      },
      "ApmSubjectHandlePath": {
        "name": "subjectHandle",
        "in": "path",
        "required": true,
        "description": "Opaque subject handle; hashed before authentication, logging, storage, or repository access.",
        "schema": {
          "type": "string",
          "minLength": 16,
          "maxLength": 512,
          "pattern": "^[A-Za-z0-9._~:/+-]+$"
        }
      },
      "ApmPrivacyRequestIdPath": {
        "name": "requestId",
        "in": "path",
        "required": true,
        "schema": {
          "$ref": "#/components/schemas/ApmScopedId"
        }
      },
      "v1_WebhookEventHeader": {
        "name": "X-Noxtica-Event",
        "in": "header",
        "required": true,
        "description": "The event type; equals `type` in the body.",
        "schema": {
          "type": "string",
          "example": "submission.scored"
        }
      },
      "v1_WebhookDeliveryHeader": {
        "name": "X-Noxtica-Delivery",
        "in": "header",
        "required": true,
        "description": "The delivery id; equals `id` in the body and is identical on every retry of the same delivery. Deduplicate on it.",
        "schema": {
          "type": "string"
        }
      }
    },
    "responses": {
      "InvalidRequest": {
        "description": "The request failed validation. `error` is a route-specific code such as `invalid_request`; read the operation description for the exact values it can return.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorEnvelope"
            },
            "example": {
              "error": "invalid_request",
              "requestId": "req-test"
            }
          }
        }
      },
      "ScopeForbidden": {
        "description": "The presented key lacks the required scope.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "error": {
                  "type": "string",
                  "example": "API key does not have write:identity scope"
                },
                "requestId": {
                  "type": "string"
                }
              }
            },
            "example": {
              "error": "API key does not have write:identity scope",
              "requestId": "req-test"
            }
          }
        }
      },
      "GatedNotFound": {
        "description": "The byte-identical \"V1 endpoint not found\" response returned when the route's module is not enabled for your organisation — indistinguishable from a route that does not exist (anti-enumeration by design; do not treat this as proof the path is wrong).",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "error": {
                  "type": "string",
                  "enum": [
                    "V1 endpoint not found"
                  ]
                },
                "path": {
                  "type": "string"
                },
                "requestId": {
                  "type": "string"
                }
              }
            },
            "example": {
              "error": "V1 endpoint not found",
              "path": "/v1/kyc/verify",
              "requestId": "req-test"
            }
          }
        }
      },
      "BodyTooLarge": {
        "description": "`body_too_large` — the request exceeded this route's byte cap.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorEnvelope"
            },
            "example": {
              "error": "body_too_large",
              "requestId": "req-test"
            }
          }
        }
      },
      "RateLimited": {
        "description": "Rate limit exceeded. Wait `Retry-After` seconds (also `retryAfter` in the body) before retrying; the response carries no other rate-limit headers.",
        "headers": {
          "Retry-After": {
            "schema": {
              "type": "integer"
            },
            "description": "Seconds until the bucket allows another request."
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "error": {
                  "type": "string",
                  "enum": [
                    "Rate limit exceeded"
                  ]
                },
                "retryAfter": {
                  "type": "integer"
                },
                "requestId": {
                  "type": "string"
                }
              }
            },
            "example": {
              "error": "Rate limit exceeded",
              "retryAfter": 1,
              "requestId": "req-test"
            }
          }
        }
      },
      "SessionExpired": {
        "description": "The session has expired — past its effective `expiresAt` (the original mint TTL while unopened, or `openedAt` plus the 30-minute capture window once opened) and never reached a terminal/completed state. The hosted verification page MUST stop polling on this response.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/KycSessionExpiredError"
            },
            "example": {
              "error": "session_expired",
              "code": "kyc_session_expired",
              "requestId": "req-test"
            }
          }
        }
      },
      "SessionExpiredOrCancelled": {
        "description": "The session can no longer be used by the hosted verification page, in one of two byte-stable shapes told apart by `code`. `kyc_session_expired` (`error: session_expired`) — the session is past its effective `expiresAt` (the original mint TTL while unopened, or `openedAt` plus the 30-minute capture window once opened) and never reached a terminal/completed state. `kyc_session_cancelled` (`error: session_cancelled`) — the end customer cancelled the session via `POST /v1/kyc/session-cancel` (terminal status `cancelled_by_user`). The hosted verification page MUST stop polling on either response.",
        "content": {
          "application/json": {
            "schema": {
              "oneOf": [
                {
                  "$ref": "#/components/schemas/KycSessionExpiredError"
                },
                {
                  "$ref": "#/components/schemas/KycSessionCancelledError"
                }
              ]
            },
            "examples": {
              "expired": {
                "value": {
                  "error": "session_expired",
                  "code": "kyc_session_expired",
                  "requestId": "req-test"
                }
              },
              "cancelled": {
                "value": {
                  "error": "session_cancelled",
                  "code": "kyc_session_cancelled",
                  "requestId": "req-test"
                }
              }
            }
          }
        }
      },
      "InvalidApiKey": {
        "description": "The `Authorization: Bearer sk_...` header is missing or malformed, or the key is unknown or revoked. The body is deliberately identical for every one of those causes.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/KycSessionError"
            },
            "example": {
              "error": "invalid_api_key",
              "message": "Invalid or revoked API key",
              "requestId": "req-test"
            }
          }
        }
      },
      "ServerMisconfigured": {
        "description": "API-key authentication is not configured on this deployment (`server_misconfigured`). Retrying does not help; contact support with the `requestId`.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/KycSessionError"
            },
            "example": {
              "error": "server_misconfigured",
              "message": "API key authentication is not configured on this server",
              "requestId": "req-test"
            }
          }
        }
      },
      "ApiError": {
        "description": "Failure in the platform `apiError` envelope.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            }
          }
        }
      },
      "pulse_RateLimited": {
        "description": "Too many attempts.",
        "headers": {
          "Retry-After": {
            "description": "Seconds until the window resets.",
            "schema": {
              "type": "integer"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            }
          }
        }
      },
      "TenantUnauthorized": {
        "description": "`missing_api_key` or `invalid_api_key` (malformed, unknown, revoked, or a device token). `WWW-Authenticate: Bearer realm=\"pulse-tenant\"`.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            }
          }
        }
      },
      "TenantForbidden": {
        "description": "`insufficient_scope` (the key lacks the scope the operation names) or `tenant_not_armed`.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            }
          }
        }
      },
      "TenantUnavailable": {
        "description": "`tenant_auth_unavailable` or `rate_limiter_unavailable` (fail closed).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            }
          }
        }
      },
      "v1_InvalidRequest": {
        "description": "The request failed validation. `error` is a route-specific string such as `Invalid body` or `invalid_request`; read the operation description for the exact values it can return.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/v1_ErrorEnvelope"
            },
            "example": {
              "error": "Invalid body",
              "requestId": "req-test"
            }
          }
        }
      },
      "v1_InvalidApiKey": {
        "description": "The `Authorization: Bearer sk_...` header is missing or malformed, or the key is unknown, revoked, or belongs to a suspended or deleted organisation. The body is deliberately identical for every cause.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/InvalidApiKeyError"
            },
            "example": {
              "error": "invalid_api_key",
              "message": "Invalid or revoked API key",
              "requestId": "req-test"
            }
          }
        }
      },
      "v1_ScopeForbidden": {
        "description": "The API key is valid but does not carry the scope this operation requires; `error` names the missing scope.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ScopeForbiddenError"
            },
            "example": {
              "error": "API key does not have read:device scope",
              "requestId": "req-test"
            }
          }
        }
      },
      "v1_GatedNotFound": {
        "description": "The byte-identical \"V1 endpoint not found\" response returned when the route's module is not enabled for your organisation, and also for a path that does not exist — indistinguishable by design (anti-enumeration), so do not treat it as proof the path is wrong.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "error": {
                  "type": "string",
                  "enum": [
                    "V1 endpoint not found"
                  ]
                },
                "path": {
                  "type": "string"
                },
                "requestId": {
                  "type": "string"
                }
              }
            },
            "example": {
              "error": "V1 endpoint not found",
              "path": "/v1/score",
              "requestId": "req-test"
            }
          }
        }
      },
      "v1_BodyTooLarge": {
        "description": "The request body exceeded this route's byte cap.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/v1_ErrorEnvelope"
            },
            "example": {
              "error": "body_too_large",
              "requestId": "req-test"
            }
          }
        }
      },
      "v1_RateLimited": {
        "description": "Rate limit exceeded. Wait `Retry-After` seconds (also `retryAfter` in the body) before retrying; the response carries no other rate-limit headers.",
        "headers": {
          "Retry-After": {
            "schema": {
              "type": "integer"
            },
            "description": "Seconds until the bucket allows another request."
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "error",
                "retryAfter"
              ],
              "properties": {
                "error": {
                  "type": "string",
                  "enum": [
                    "Rate limit exceeded"
                  ]
                },
                "retryAfter": {
                  "type": "integer",
                  "description": "Seconds to wait; equals the `Retry-After` header."
                },
                "requestId": {
                  "type": "string"
                }
              }
            },
            "example": {
              "error": "Rate limit exceeded",
              "retryAfter": 12,
              "requestId": "req-test"
            }
          }
        }
      },
      "InternalError": {
        "description": "Unexpected server fault. Retry with backoff and quote `requestId` to support if it persists.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/v1_ErrorEnvelope"
            },
            "example": {
              "error": "Internal server error",
              "requestId": "req-test"
            }
          }
        }
      },
      "ApmInvalid": {
        "description": "Closed-input validation failed.",
        "headers": {
          "Cache-Control": {
            "$ref": "#/components/headers/NoStore"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApmError"
            },
            "example": {
              "ok": false,
              "error": "invalid_request",
              "reason": "invalid_range",
              "requestId": "req-test"
            }
          }
        }
      },
      "ApmUnauthorized": {
        "description": "Missing, invalid, or ingest-only credential. An `sk_apm_` key is never accepted here.",
        "headers": {
          "Cache-Control": {
            "$ref": "#/components/headers/NoStore"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApmError"
            },
            "example": {
              "ok": false,
              "error": "Unauthorized",
              "requestId": "req-test"
            }
          }
        }
      },
      "ApmForbidden": {
        "description": "The server API key lacks the operation's required scope.",
        "headers": {
          "Cache-Control": {
            "$ref": "#/components/headers/NoStore"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApmError"
            },
            "example": {
              "ok": false,
              "error": "API key does not have read:apm scope",
              "requestId": "req-test"
            }
          }
        }
      },
      "ApmNotFound": {
        "description": "The tenant-scoped resource was not found.",
        "headers": {
          "Cache-Control": {
            "$ref": "#/components/headers/NoStore"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApmError"
            },
            "example": {
              "ok": false,
              "error": "resource_not_found",
              "requestId": "req-test"
            }
          }
        }
      },
      "ApmRateLimited": {
        "description": "V1 read rate limit exceeded.",
        "headers": {
          "Cache-Control": {
            "$ref": "#/components/headers/NoStore"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApmRateLimitError"
            },
            "example": {
              "ok": false,
              "error": "Rate limit exceeded",
              "retryAfter": 60,
              "requestId": "req-test"
            }
          }
        }
      },
      "ApmControlUnavailable": {
        "description": "Authoritative control-plane data is unavailable.",
        "headers": {
          "Cache-Control": {
            "$ref": "#/components/headers/NoStore"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApmUnavailable"
            },
            "example": {
              "ok": false,
              "available": false,
              "reason": "control_plane_unavailable",
              "requestId": "req-test"
            }
          }
        }
      },
      "ApmWarehouseUnavailable": {
        "description": "Warehouse query or mandatory access audit is unavailable.",
        "headers": {
          "Cache-Control": {
            "$ref": "#/components/headers/NoStore"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApmUnavailable"
            },
            "example": {
              "ok": false,
              "available": false,
              "reason": "warehouse_unavailable",
              "requestId": "req-test"
            }
          }
        }
      },
      "ApmInternal": {
        "description": "Unexpected internal trace-query failure.",
        "headers": {
          "Cache-Control": {
            "$ref": "#/components/headers/NoStore"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApmError"
            },
            "example": {
              "ok": false,
              "error": "internal_error",
              "requestId": "req-test"
            }
          }
        }
      },
      "CodingAgentUnauthorized": {
        "description": "`coding_agent_auth_missing` (no `Authorization` header) or `coding_agent_auth_invalid` (a malformed, unknown, revoked or inactive coding-agent key).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/CodingAgentError"
            },
            "example": {
              "code": 401,
              "message": "Authentication failed",
              "error": "coding_agent_auth_invalid"
            }
          }
        }
      },
      "CodingAgentScopeDenied": {
        "description": "`coding_agent_scope_denied` — the key is valid but lacks the scope this route requires.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/CodingAgentError"
            },
            "example": {
              "code": 403,
              "message": "Authentication failed",
              "error": "coding_agent_scope_denied"
            }
          }
        }
      },
      "CodingAgentRateLimited": {
        "description": "`coding_agent_rate_limited` — the per-key request limit was exceeded. Wait `Retry-After` seconds before retrying.",
        "headers": {
          "Retry-After": {
            "schema": {
              "type": "integer"
            },
            "description": "Seconds until the key may call again."
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/CodingAgentError"
            },
            "example": {
              "code": 429,
              "message": "Rate limit exceeded for this coding-agent key",
              "error": "coding_agent_rate_limited"
            }
          }
        }
      },
      "CodingAgentQueryFailed": {
        "description": "`coding_agent_query_failed` — the read query failed. Retry with backoff.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/CodingAgentError"
            },
            "example": {
              "code": 502,
              "message": "Read query failed",
              "error": "coding_agent_query_failed"
            }
          }
        }
      },
      "CodingAgentUnavailable": {
        "description": "`coding_agent_authority_unavailable` (the key could not be checked) or `coding_agent_bq_unavailable` (the read store is not available). Retry with backoff.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/CodingAgentError"
            },
            "example": {
              "code": 503,
              "message": "Authority lookup failed",
              "error": "coding_agent_authority_unavailable"
            }
          }
        }
      }
    },
    "schemas": {
      "ErrorEnvelope": {
        "type": "object",
        "required": [
          "error",
          "requestId"
        ],
        "properties": {
          "error": {
            "type": "string"
          },
          "requestId": {
            "type": "string"
          }
        }
      },
      "ConflictError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "example": "idempotency_conflict"
          },
          "code": {
            "type": "string"
          },
          "ok": {
            "type": "boolean"
          },
          "verificationId": {
            "type": "string"
          },
          "reasonCodes": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "request_in_progress"
              ]
            }
          },
          "requestId": {
            "type": "string"
          }
        }
      },
      "KycVerifyMintRequest": {
        "type": "object",
        "required": [
          "action"
        ],
        "description": "`POST /v1/kyc/verify` with `action:'mint'`. Mints a fresh, tenant-scoped, single-use admission nonce (TTL 300s) bound in KV to the calling tenant — the ONLY way a server-to-server caller can legitimately obtain a nonce a subsequent `action:'verify'` call will accept. Runs the same auth/module-gate/legal-basis preflight as verify; NEVER meters, NEVER reserves spend, makes ZERO provider calls. The `Idempotency-Key` header is not required (and is ignored) for this branch.",
        "properties": {
          "action": {
            "type": "string",
            "enum": [
              "mint"
            ],
            "description": "Selects the mint branch of this endpoint."
          }
        }
      },
      "KycVerifyRequest": {
        "description": "The body of `POST /v1/kyc/verify` — either branch selected by `action` (`verify` is the implicit default when `action` is omitted). Named as its own component (rather than an inline `oneOf`) so `openapi/generate.sh`'s csharp/generichost codegen produces a distinct composed wrapper type instead of colliding with either member schema's own generated name.",
        "oneOf": [
          {
            "$ref": "#/components/schemas/KycVerifyMintRequest"
          },
          {
            "$ref": "#/components/schemas/KycVerifyVerifyRequest"
          }
        ]
      },
      "KycVerifyVerifyRequest": {
        "type": "object",
        "required": [
          "nonce",
          "id_type"
        ],
        "properties": {
          "action": {
            "type": "string",
            "enum": [
              "verify"
            ],
            "default": "verify",
            "description": "Optional; `verify` is the implicit default when this field is omitted — every pre-existing caller is unaffected."
          },
          "nonce": {
            "type": "string",
            "description": "A fresh, tenant-scoped single-use admission nonce (minted by your own prior client-side flow / SDK step)."
          },
          "id_type": {
            "type": "string",
            "description": "Document/verification type hint for the resolved provider adapter (aliases: idType)."
          },
          "purpose": {
            "type": "string",
            "default": "identity_verification",
            "description": "One of the closed evidence-purpose catalog values."
          },
          "audience": {
            "type": "string",
            "description": "Defaults to the caller's own tenant id."
          },
          "deviceContext": {
            "type": "boolean",
            "description": "When true and device-intel is armed for the tenant, the response carries an ADVISORY deviceTrust block. Never influences the KYC verdict itself."
          },
          "payload": {
            "type": "object",
            "description": "Provider-specific verification payload (never logged or persisted verbatim). `verifiedDateOfBirth` and `minimumAge` keys are always stripped server-side before reaching any adapter — supplying them has no effect (defense-in-depth against self-attested age/DOB)."
          }
        }
      },
      "KycVerifyResponse": {
        "type": "object",
        "required": [
          "ok",
          "verdict",
          "verificationLevel",
          "reasonCodes",
          "verificationId",
          "requestId"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "verdict": {
            "type": "string",
            "enum": [
              "verified",
              "unverified",
              "error"
            ],
            "description": "`error` is an infra/provider fault, never a statement about the subject — always HTTP 200 (FR-6)."
          },
          "verificationLevel": {
            "type": "string",
            "enum": [
              "verified",
              "partial",
              "unverified",
              "inconclusive"
            ]
          },
          "reasonCodes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/KycReasonCode"
            }
          },
          "verificationId": {
            "type": "string",
            "format": "uuid"
          },
          "requestId": {
            "type": "string"
          },
          "legalBasisRef": {
            "type": "string",
            "description": "Present only when this request's tenant is running under classified legal-basis receipt gating."
          },
          "nfcAssurance": {
            "type": "object",
            "description": "Present only for eMRTD/passport-chip verification paths."
          },
          "deviceTrust": {
            "type": "object",
            "description": "Present only when the request set deviceContext:true and device-intel evidence is available. ADVISORY ONLY — never fed back into verdict/reasonCodes."
          }
        }
      },
      "KycVerifyMintResponse": {
        "type": "object",
        "required": [
          "ok",
          "nonce",
          "ttlSeconds"
        ],
        "description": "The success shape for `POST /v1/kyc/verify` with `action:'mint'`.",
        "properties": {
          "ok": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "nonce": {
            "type": "string",
            "format": "uuid",
            "description": "Pass back verbatim as `nonce` on the follow-up `action:'verify'` (or omitted-action) call, from the SAME tenant, before it expires."
          },
          "ttlSeconds": {
            "type": "integer",
            "description": "Absolute KV expiry from mint time (300s as of 2026-09-13, `KYC_NONCE_TTL_SECONDS`). A verify attempt after this window elapses returns `reasonCodes:[nonce_expired]`; an unminted, already-consumed, or wrong-tenant nonce returns `reasonCodes:[nonce_unknown]`."
          }
        }
      },
      "KycReasonCode": {
        "type": "string",
        "description": "The closed, append-only KYC reason-code catalog. A raw provider string is NEVER returned verbatim — every provider token is mapped to one of these or to the generic `provider_unknown` fallback. Grouped families: `provider_*` (transport/lifecycle faults, ≤15), verification-match outcomes (`name_match`/`document_expired`/ `face_match`/`liveness_passed`/etc.), `nonce_*`/`request_*` (admission lifecycle), `subject_*` (linkage), `device_trust_*` (advisory), `adapter_*`/`callback_*` (non-documentary adapter foundation), `account_ownership_*` (bank ownership), `telco_*` (SIM-swap/number-verify — risk signals, never alone `verified`), `age_*` (age assurance), `evidence_*` (post-upload inspection), `policy_*` (response-side enforcement), `emrtd_*` (server-authoritative eMRTD passive authentication), `liveness_injection_*` (injection-detection, separate from the liveness verdict itself).",
        "enum": [
          "provider_timeout",
          "provider_unreachable",
          "provider_rejected",
          "provider_error",
          "provider_unknown",
          "provider_rate_limited",
          "provider_invalid_request",
          "provider_unsupported_id_type",
          "provider_manual_review",
          "provider_expired",
          "name_match",
          "name_mismatch",
          "dob_match",
          "dob_mismatch",
          "document_authentic",
          "document_expired",
          "document_tampered",
          "address_match",
          "address_mismatch",
          "face_match",
          "face_mismatch",
          "liveness_passed",
          "liveness_failed",
          "nonce_unknown",
          "nonce_expired",
          "nonce_consumed",
          "nonce_binding_mismatch",
          "request_in_progress",
          "request_storage_error",
          "subject_unavailable",
          "subject_linkage_failed",
          "device_trust_unavailable",
          "adapter_not_configured",
          "adapter_config_invalid",
          "callback_signature_invalid",
          "callback_timestamp_expired",
          "callback_replay",
          "account_ownership_match",
          "account_ownership_mismatch",
          "telco_sim_swap_recent",
          "telco_sim_swap_none",
          "telco_number_verified",
          "telco_number_mismatch",
          "age_meets_threshold",
          "age_below_threshold",
          "age_dob_unavailable",
          "age_estimate_inconclusive",
          "age_policy_not_configured",
          "age_dob_unverified",
          "callback_claim_error",
          "evidence_kind_forbidden",
          "evidence_mime_mismatch",
          "evidence_size_mismatch",
          "evidence_pixels_invalid",
          "evidence_unreadable",
          "policy_blocked",
          "policy_challenge_required",
          "emrtd_malformed_asn1",
          "emrtd_sod_signature_invalid",
          "emrtd_dg_hash_mismatch",
          "emrtd_csca_untrusted",
          "emrtd_csca_expired",
          "emrtd_csca_trust_store_unavailable",
          "emrtd_client_claim_ignored",
          "emrtd_verified",
          "emrtd_dg1_required",
          "emrtd_partial_no_chip_authentication",
          "liveness_injection_check_passed",
          "liveness_injection_check_failed",
          "liveness_injection_check_unavailable",
          "liveness_client_claim_ignored",
          "subject_missing_on_verified",
          "subject_invalid_on_verified",
          "subject_link_failed"
        ]
      },
      "KycBatchManifestJson": {
        "type": "object",
        "required": [
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "maxItems": 500,
            "items": {
              "type": "object",
              "required": [
                "id_type"
              ],
              "properties": {
                "id_type": {
                  "type": "string"
                },
                "purpose": {
                  "type": "string",
                  "default": "identity_verification"
                },
                "payload": {
                  "type": "object"
                }
              }
            }
          }
        }
      },
      "KycBatchItemErrorCode": {
        "type": "string",
        "enum": [
          "missing_id_type",
          "invalid_row_shape",
          "admission_replay",
          "admission_in_progress",
          "admission_binding_mismatch",
          "admission_expired",
          "admission_storage_error"
        ]
      },
      "KycBatchSubmittedItem": {
        "type": "object",
        "properties": {
          "rowIndex": {
            "type": "integer"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "admitted",
              "evaluating",
              "completed",
              "rejected",
              "cancelled"
            ]
          },
          "errorCode": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/KycBatchItemErrorCode"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "KycBatchSubmitResponse": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "batchId": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "processing",
              "completed",
              "cancelled"
            ]
          },
          "itemCount": {
            "type": "integer"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/KycBatchSubmittedItem"
            }
          },
          "requestId": {
            "type": "string"
          }
        }
      },
      "KycBatchStatusResponse": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "batchId": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "processing",
              "completed",
              "cancelled"
            ]
          },
          "itemCount": {
            "type": "integer"
          },
          "pendingCount": {
            "type": "integer"
          },
          "admittedCount": {
            "type": "integer"
          },
          "completedCount": {
            "type": "integer"
          },
          "rejectedCount": {
            "type": "integer"
          },
          "cancelledCount": {
            "type": "integer"
          },
          "requestId": {
            "type": "string"
          }
        }
      },
      "KycBatchResultsResponse": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "batchId": {
            "type": "string"
          },
          "items": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "rowIndex": {
                  "type": "integer"
                },
                "status": {
                  "type": "string",
                  "enum": [
                    "pending",
                    "admitted",
                    "evaluating",
                    "completed",
                    "rejected",
                    "cancelled"
                  ]
                },
                "verificationId": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "verdict": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "enum": [
                    "verified",
                    "unverified",
                    "error",
                    null
                  ]
                },
                "errorCode": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/KycBatchItemErrorCode"
                    },
                    {
                      "type": "null"
                    }
                  ]
                }
              }
            }
          },
          "requestId": {
            "type": "string"
          }
        }
      },
      "KymTransactionResponse": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "eventId": {
            "type": "string"
          },
          "deduplicated": {
            "type": "boolean"
          },
          "requestId": {
            "type": "string"
          }
        }
      },
      "KycSessionError": {
        "type": "object",
        "description": "The error body of the hosted-session S2S routes. `error` is a closed machine code; `message` accompanies a few of them; `reason` and `reasonCode` are additive refinements.",
        "required": [
          "error",
          "requestId"
        ],
        "properties": {
          "error": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "reason": {
            "type": "string",
            "enum": [
              "pg_unavailable",
              "backend_unavailable"
            ],
            "description": "Present on the retryable `503` answers; says which dependency could not answer."
          },
          "reasonCode": {
            "type": "string",
            "enum": [
              "age_gender_platform_disabled",
              "age_gender_tenant_acknowledgement_missing"
            ],
            "description": "Present on `403 age_gender_estimation_not_enabled` only."
          },
          "requestId": {
            "type": "string"
          }
        }
      },
      "KycSessionStatus": {
        "type": "string",
        "enum": [
          "pending",
          "opened",
          "verifying",
          "review_pending",
          "completed",
          "unverified",
          "error",
          "expired",
          "cancelled_by_user"
        ],
        "description": "The hosted session lifecycle status. `pending` — minted, link not opened yet. `opened` — the customer reached the capture page. `verifying` — the customer submitted and the verification is running. `review_pending` — the verification finished and awaits a Backoffice review decision (today every successful hosted capture lands here; it never expires, and `kyc.session.completed` has NOT fired yet). `completed` — a business decision exists. `unverified` — finished with a negative outcome and no manual-review code. `error` — a provider or infrastructure fault, or the submit was refused at admission. `expired` — the effective deadline passed without a decision (reported by the status read; no webhook). `cancelled_by_user` — the customer cancelled on the hosted page."
      },
      "KycSessionCaptureStep": {
        "type": "string",
        "enum": [
          "consent",
          "id_front",
          "id_back",
          "selfie",
          "document_near_face",
          "liveness",
          "voice",
          "review",
          "submit"
        ],
        "description": "The furthest capture step the customer has reached."
      },
      "KycSessionEvidenceRefs": {
        "type": "object",
        "description": "Opaque object ids of the finalized (usable) uploads, by role. Never a URL or media bytes. A role appears only once its upload is finalized.",
        "properties": {
          "front": {
            "type": "string"
          },
          "back": {
            "type": "string"
          },
          "selfie": {
            "type": "string"
          },
          "voice": {
            "type": "string"
          },
          "documentNearFace": {
            "type": "string"
          }
        }
      },
      "KycSessionDecision": {
        "type": "object",
        "description": "The decision block, present once the pipeline or a review decision has produced one. `outcome` maps from the session status: `completed` to `approved`, `unverified` to `rejected`, `review_pending` to `review_pending`, `error` to `error`.",
        "required": [
          "outcome",
          "reasonCodes",
          "decidedAt"
        ],
        "properties": {
          "outcome": {
            "type": "string",
            "enum": [
              "approved",
              "rejected",
              "review_pending",
              "error"
            ]
          },
          "reasonCodes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "decidedAt": {
            "type": "integer",
            "format": "int64",
            "description": "Unix ms."
          }
        }
      },
      "KycTenantStageResult": {
        "type": "object",
        "description": "One analysis stage's tenant-facing result. Stages that carry extra advisory detail (`speech_profile`, `age_gender`, `scene_inventory`, `document_type_id`) add typed members next to these three; model and engine provenance is never exposed.",
        "required": [
          "status",
          "score",
          "reasonCodes"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "pass",
              "review",
              "fail",
              "skipped",
              "pending"
            ]
          },
          "score": {
            "type": [
              "number",
              "null"
            ],
            "description": "Range 0 to 1, or `null` when the stage produced no score."
          },
          "reasonCodes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "KycTenantStages": {
        "type": "object",
        "description": "Per-stage results keyed by stage name. A stage that was not requested or has not run reads `status: skipped` or `pending` with a reason code, never a fabricated pass.",
        "properties": {
          "scene_inventory": {
            "$ref": "#/components/schemas/KycTenantStageResult"
          },
          "document_type_id": {
            "$ref": "#/components/schemas/KycTenantStageResult"
          },
          "ocr_back": {
            "$ref": "#/components/schemas/KycTenantStageResult"
          },
          "mrz_crosscheck": {
            "$ref": "#/components/schemas/KycTenantStageResult"
          },
          "selfie_quality": {
            "$ref": "#/components/schemas/KycTenantStageResult"
          },
          "document_near_face": {
            "$ref": "#/components/schemas/KycTenantStageResult"
          },
          "active_liveness": {
            "$ref": "#/components/schemas/KycTenantStageResult"
          },
          "speech_profile": {
            "$ref": "#/components/schemas/KycTenantStageResult"
          },
          "speech_analysis": {
            "$ref": "#/components/schemas/KycTenantStageResult"
          },
          "age_gender": {
            "$ref": "#/components/schemas/KycTenantStageResult"
          }
        }
      },
      "KycScorecardEntry": {
        "type": "object",
        "required": [
          "status",
          "score",
          "checks",
          "reasonCodes"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "pass",
              "review",
              "fail",
              "skipped",
              "pending"
            ]
          },
          "score": {
            "type": "number",
            "description": "Range 0 to 1; `0` for `pending` and `skipped` (no evaluation occurred)."
          },
          "checks": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "name",
                "pass"
              ],
              "properties": {
                "name": {
                  "type": "string"
                },
                "pass": {
                  "type": "boolean"
                },
                "score": {
                  "type": [
                    "number",
                    "null"
                  ]
                }
              }
            }
          },
          "reasonCodes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "KycTenantScorecard": {
        "type": "object",
        "description": "The numeric per-step summary. A non-authoritative roll-up of what the pipeline already decided: never an approval by itself. `overall` is the roll-up of the other six.",
        "properties": {
          "document_front": {
            "$ref": "#/components/schemas/KycScorecardEntry"
          },
          "document_back": {
            "$ref": "#/components/schemas/KycScorecardEntry"
          },
          "selfie": {
            "$ref": "#/components/schemas/KycScorecardEntry"
          },
          "liveness": {
            "$ref": "#/components/schemas/KycScorecardEntry"
          },
          "voice": {
            "$ref": "#/components/schemas/KycScorecardEntry"
          },
          "cross_validation": {
            "$ref": "#/components/schemas/KycScorecardEntry"
          },
          "overall": {
            "$ref": "#/components/schemas/KycScorecardEntry"
          }
        }
      },
      "KycTenantSessionEnvelope": {
        "type": "object",
        "description": "The wire envelope of `GET /v1/kyc/sessions/{sessionId}`. The session fields are always nested under `session`, never flattened onto the envelope.",
        "required": [
          "ok",
          "session",
          "requestId"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "session": {
            "$ref": "#/components/schemas/KycTenantSessionStatus"
          },
          "requestId": {
            "type": "string"
          }
        }
      },
      "KycTenantSessionStatus": {
        "type": "object",
        "description": "The tenant-backend view of a hosted session. Every timestamp is Unix time in **milliseconds**. Not exposed on this route: the session URL or token, evidence bytes or URLs, the stored `hostedOptions`, `cancelledAt` and `cancelReason` (those are delivered only in the `kyc.session.cancelled` webhook), model provenance, and the address a person may have given to receive their Noxtica Verification ID.",
        "required": [
          "id",
          "status",
          "idType",
          "subjectId",
          "captureStep",
          "createdAt",
          "openedAt",
          "expiresAt",
          "completedAt",
          "verificationId",
          "reasonCodes",
          "purpose",
          "returnUrl",
          "selectedIdType",
          "selectedIssuingCountry",
          "consentVersion",
          "consentAcceptedAt",
          "speechProfilingConsentAcceptedAt",
          "ageGenderConsentAcceptedAt",
          "evidence",
          "stages",
          "scorecard"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "The session id returned by the mint call."
          },
          "status": {
            "$ref": "#/components/schemas/KycSessionStatus"
          },
          "idType": {
            "type": "string",
            "description": "The document type hint given at mint (default `national_id`)."
          },
          "subjectId": {
            "type": "string",
            "description": "Your own `subjectRef` from the mint call, returned unchanged. It is never sent in webhooks."
          },
          "captureStep": {
            "$ref": "#/components/schemas/KycSessionCaptureStep"
          },
          "createdAt": {
            "type": "integer",
            "format": "int64"
          },
          "openedAt": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "When the customer first opened the link; `null` until then."
          },
          "expiresAt": {
            "type": "integer",
            "format": "int64",
            "description": "The effective deadline. Equal to the mint-time deadline while the link is unopened; once the customer opens it, tightened to `min(expiresAt, openedAt + 1800000)` (the 30-minute capture window). A session in `review_pending` does not expire."
          },
          "completedAt": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "When the decision was made (pipeline outcome, or the reviewer's decision for a session that was `review_pending`); `null` before."
          },
          "verificationId": {
            "type": [
              "string",
              "null"
            ],
            "description": "The verification the submit ran (also `data.verificationId` of `kyc.verification.completed`); `null` before the customer submits."
          },
          "reasonCodes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Closed reason-code catalog. `provider_manual_review` means the case is waiting for a manual review."
          },
          "purpose": {
            "type": [
              "string",
              "null"
            ],
            "description": "The mint-time `purpose`."
          },
          "returnUrl": {
            "type": [
              "string",
              "null"
            ],
            "description": "The mint-time `returnUrl`."
          },
          "selectedIdType": {
            "type": [
              "string",
              "null"
            ],
            "description": "The document type the customer chose on the page."
          },
          "selectedIssuingCountry": {
            "type": [
              "string",
              "null"
            ],
            "description": "The issuing country the customer chose."
          },
          "consentVersion": {
            "type": [
              "string",
              "null"
            ],
            "description": "Version of the privacy notice the customer acknowledged."
          },
          "consentAcceptedAt": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          },
          "speechProfilingConsentAcceptedAt": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          },
          "ageGenderConsentAcceptedAt": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          },
          "evidence": {
            "$ref": "#/components/schemas/KycSessionEvidenceRefs"
          },
          "decision": {
            "$ref": "#/components/schemas/KycSessionDecision"
          },
          "crossValidation": {
            "type": "object",
            "description": "The OCR / MRZ / barcode cross-validation advisory block, when the pipeline attached one. Absent for sessions without back-of-document evidence. Verdict-neutral."
          },
          "stages": {
            "$ref": "#/components/schemas/KycTenantStages"
          },
          "scorecard": {
            "$ref": "#/components/schemas/KycTenantScorecard"
          },
          "email": {
            "type": [
              "string",
              "null"
            ],
            "description": "Present only when hosted email verification is enabled for your organisation AND (the session's effective `emailVerification` mode is not `off` OR an address is stored). The normalised address the customer entered, or `null`. It is the customer's own typed value until `emailVerified` is `true`."
          },
          "emailVerified": {
            "type": "boolean",
            "description": "Present under the same condition as `email`. `true` only after the customer clicked the confirmation link for that exact address."
          },
          "emailVerifiedAt": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "Present under the same condition as `email`. When the confirmation link was clicked, or `null`."
          },
          "emailVerification": {
            "$ref": "#/components/schemas/KycEmailVerificationMode"
          },
          "nvid": {
            "type": [
              "string",
              "null"
            ],
            "description": "Present only when the Noxtica Verification ID is enabled for your organisation. The session's NVID (`NVID-XXXX-XXXX-XXXX-XXXX`), or `null` when none was issued (an NVID is issued when the submit ends `completed` or `review_pending`). The public status of an NVID is read from `GET /v1/kyc/verification-status`, which only the hosted verification site's browser origin may call; a tenant backend takes the NVID from this field or from `data.nvid` of `kyc.session.completed`."
          }
        }
      },
      "KycHostedSessionEnvelope": {
        "type": "object",
        "description": "The wire envelope of the hosted page's snapshot routes (`GET /v1/kyc/session-view` and `POST /v1/kyc/session-progress`). The session fields are never flattened onto the envelope. The tenant-backend status read has its own shape, `KycTenantSessionEnvelope`.",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "session": {
            "$ref": "#/components/schemas/KycHostedSessionSnapshot"
          },
          "requestId": {
            "type": "string"
          }
        }
      },
      "KycHostedSessionSnapshot": {
        "type": "object",
        "description": "The customer-facing snapshot the hosted verification page renders from. Called by the page itself, never by a tenant backend; it is not a stable integration surface. All timestamps are Unix milliseconds. Optional members appear only when the matching capability is active for the session.",
        "required": [
          "status",
          "idType",
          "captureStep",
          "expiresAt",
          "openedAt",
          "steps",
          "configuration",
          "selection",
          "consent",
          "evidence",
          "resume",
          "failureBudget",
          "serverNow",
          "sessionExpiresAt"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/KycSessionStatus"
          },
          "idType": {
            "type": "string"
          },
          "captureStep": {
            "$ref": "#/components/schemas/KycSessionCaptureStep"
          },
          "expiresAt": {
            "type": "integer",
            "format": "int64",
            "description": "Effective session deadline: the original mint-time deadline while the link is unopened, tightened in place to `openedAt + 1800000` (the 30-minute capture window) once opened, whichever is sooner."
          },
          "openedAt": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "When the customer's first hosted-flow action landed (the `pending` to `opened` transition); `null` until then."
          },
          "steps": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/KycSessionCaptureStep"
            },
            "description": "The full step vocabulary, in order."
          },
          "configuration": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/KycHostedSessionConfiguration"
              },
              {
                "type": "null"
              }
            ],
            "description": "The tenant's hosted setup filtered by this session's options; `null` when the tenant has no hosted configuration (the page shows \"Verification isn't ready yet\")."
          },
          "selection": {
            "oneOf": [
              {
                "type": "object",
                "required": [
                  "idType",
                  "issuingCountry"
                ],
                "properties": {
                  "idType": {
                    "type": "string"
                  },
                  "issuingCountry": {
                    "type": "string"
                  }
                }
              },
              {
                "type": "null"
              }
            ],
            "description": "The customer's document choice, once made."
          },
          "consent": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/KycHostedSessionConsent"
              },
              {
                "type": "null"
              }
            ],
            "description": "The privacy-notice receipt; immutable once set."
          },
          "biometricConsent": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/KycHostedSessionConsent"
              },
              {
                "type": "null"
              }
            ],
            "description": "The biometric-processing consent receipt. Present only when biometric consent is enabled for the platform."
          },
          "speechProfilingConsent": {
            "type": "object",
            "required": [
              "acceptedAt"
            ],
            "properties": {
              "acceptedAt": {
                "type": "integer",
                "format": "int64"
              }
            }
          },
          "ageGenderConsent": {
            "type": "object",
            "required": [
              "acceptedAt"
            ],
            "properties": {
              "acceptedAt": {
                "type": "integer",
                "format": "int64"
              }
            }
          },
          "evidence": {
            "$ref": "#/components/schemas/KycSessionEvidenceRefs"
          },
          "resume": {
            "$ref": "#/components/schemas/KycHostedSessionResume"
          },
          "decision": {
            "$ref": "#/components/schemas/KycSessionDecision"
          },
          "processing": {
            "type": "object",
            "description": "Coarse \"what is happening now\" for the status page; absent while the customer is still capturing.",
            "required": [
              "stage",
              "updatedAt"
            ],
            "properties": {
              "stage": {
                "type": "string",
                "enum": [
                  "uploading",
                  "queued",
                  "evaluating",
                  "review_pending",
                  "decided"
                ]
              },
              "updatedAt": {
                "type": "integer",
                "format": "int64"
              }
            }
          },
          "evidenceQuality": {
            "type": "object",
            "description": "Per-role structural quality receipt; absent until a role's evidence has been inspected."
          },
          "livenessSteps": {
            "type": "array",
            "description": "The configured liveness challenge with per-step completion.",
            "items": {
              "type": "object",
              "required": [
                "id",
                "kind",
                "completed"
              ],
              "properties": {
                "id": {
                  "type": "string"
                },
                "kind": {
                  "type": "string"
                },
                "completed": {
                  "type": "boolean"
                }
              }
            }
          },
          "voiceChallenge": {
            "type": "object",
            "description": "The anti-replay digit phrase; present only when the tenant requires the voice step.",
            "required": [
              "phrase"
            ],
            "properties": {
              "phrase": {
                "type": "string"
              }
            }
          },
          "failureBudget": {
            "type": "object",
            "description": "Attempt counters per retryable step (`front`, `back`, `selfie`, `liveness`, `voice`, `upload`).",
            "additionalProperties": {
              "type": "object",
              "required": [
                "attempts",
                "max"
              ],
              "properties": {
                "attempts": {
                  "type": "integer"
                },
                "max": {
                  "type": "integer"
                }
              }
            }
          },
          "deviceChoice": {
            "type": "string",
            "enum": [
              "desktop",
              "phone"
            ],
            "description": "A previously recorded cross-device continuation choice; absent when none was recorded."
          },
          "serverNow": {
            "type": "integer",
            "format": "int64",
            "description": "The server clock when the snapshot was built; the page computes remaining time against it, not against its own clock."
          },
          "sessionExpiresAt": {
            "type": "integer",
            "format": "int64",
            "description": "The same deadline as `expiresAt`, named for the two-timer UI."
          },
          "currentStep": {
            "type": [
              "string",
              "null"
            ],
            "description": "The step the customer most recently entered. Present only when per-step timers are enabled for the platform."
          },
          "stepStartedAt": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          },
          "stepExpiresAt": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "`min(stepStartedAt + 10 minutes, sessionExpiresAt)`; `null` for an untimed step."
          },
          "capabilities": {
            "$ref": "#/components/schemas/KycHostedSessionCapabilities"
          },
          "emailVerification": {
            "$ref": "#/components/schemas/KycEmailVerificationState"
          },
          "verificationIdentifier": {
            "description": "Present only while the NVID is enabled for the platform; `null` when the session has none.",
            "oneOf": [
              {
                "$ref": "#/components/schemas/KycVerificationIdentifier"
              },
              {
                "type": "null"
              }
            ]
          },
          "evidenceUpload": {
            "type": "object",
            "description": "Capability marker for step-wise evidence upload; present only when that capability is enabled for the platform."
          },
          "evidenceReceipts": {
            "type": "object",
            "description": "Server-authoritative per-step evidence receipts; present with `evidenceUpload`."
          },
          "scorecard": {
            "type": "object",
            "description": "The customer-masked per-step scorecard (`GET /v1/kyc/session-view` only): a status per step and nothing else; no score, check or reason code reaches a browser. The full numeric version is `session.scorecard` on the tenant status read.",
            "properties": {
              "document_front": {
                "$ref": "#/components/schemas/KycCustomerScorecardEntry"
              },
              "document_back": {
                "$ref": "#/components/schemas/KycCustomerScorecardEntry"
              },
              "selfie": {
                "$ref": "#/components/schemas/KycCustomerScorecardEntry"
              },
              "liveness": {
                "$ref": "#/components/schemas/KycCustomerScorecardEntry"
              },
              "voice": {
                "$ref": "#/components/schemas/KycCustomerScorecardEntry"
              },
              "cross_validation": {
                "$ref": "#/components/schemas/KycCustomerScorecardEntry"
              },
              "overall": {
                "$ref": "#/components/schemas/KycCustomerScorecardEntry"
              }
            }
          }
        }
      },
      "KycCustomerScorecardEntry": {
        "type": "object",
        "required": [
          "status"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "pass",
              "needs_review",
              "failed",
              "skipped",
              "pending"
            ]
          }
        }
      },
      "KycHostedSessionConsent": {
        "type": "object",
        "required": [
          "version",
          "acceptedAt"
        ],
        "properties": {
          "version": {
            "type": "string"
          },
          "acceptedAt": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "KycHostedSessionConfiguration": {
        "type": "object",
        "required": [
          "businessName",
          "purpose",
          "privacyUrl",
          "supportUrl",
          "returnUrl",
          "privacyVersion",
          "documents",
          "requireSelfie",
          "requireVoice",
          "livenessMode",
          "options"
        ],
        "properties": {
          "businessName": {
            "type": "string"
          },
          "purpose": {
            "type": "string"
          },
          "privacyUrl": {
            "type": "string"
          },
          "supportUrl": {
            "type": [
              "string",
              "null"
            ]
          },
          "returnUrl": {
            "type": [
              "string",
              "null"
            ],
            "description": "The mint-time `returnUrl`. The page renders it only as a \"Return to <business>\" link (completed outcome, or the screen shown when a step cannot continue); nothing is appended and nothing redirects automatically."
          },
          "privacyVersion": {
            "type": "string"
          },
          "biometricConsentVersion": {
            "type": "string",
            "description": "Present only when biometric consent is enabled for the platform."
          },
          "documents": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "idType",
                "issuingCountries",
                "requireBack"
              ],
              "properties": {
                "idType": {
                  "type": "string",
                  "enum": [
                    "national_id",
                    "passport",
                    "driving_license",
                    "residence_permit"
                  ]
                },
                "issuingCountries": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                "requireBack": {
                  "type": "boolean"
                }
              }
            }
          },
          "requireSelfie": {
            "type": "boolean"
          },
          "requireVoice": {
            "type": "boolean"
          },
          "livenessMode": {
            "type": "string",
            "enum": [
              "passive",
              "assisted_review",
              "full_challenge"
            ]
          },
          "options": {
            "$ref": "#/components/schemas/KycHostedSessionOptions"
          }
        }
      },
      "KycHostedSessionResume": {
        "type": "object",
        "description": "Whether the customer link this snapshot answers for is still usable for further capture.",
        "required": [
          "eligible"
        ],
        "properties": {
          "eligible": {
            "type": "boolean"
          },
          "reason": {
            "type": "string",
            "enum": [
              "expired",
              "completed",
              "consumed",
              "cancelled"
            ],
            "description": "Present when `eligible` is `false`. `cancelled` means the session is in the terminal `cancelled_by_user` status (defensive — every customer route already answers `410 session_cancelled` for such a session, so a snapshot of a cancelled row is not normally served to the hosted page)."
          }
        }
      },
      "KycHostedSessionCapabilities": {
        "type": "object",
        "description": "Server capabilities the hosted verification page may rely on. The object lists only the capabilities that are active for this session and is omitted entirely when none is. `cancel` is advertised when the collector serves `POST /v1/kyc/session-cancel` AND has cancel armed; `emailVerification` is advertised when hosted email verification is enabled for the platform and the session's effective mode is not `off`. The hosted page treats \"field present\" as the only capability signal (it never probes a route, since a probe could itself create state) and, when a capability is absent, falls back to the behaviour of an older collector (for cancel: a client-only end screen with no network call; for email verification: no email step).",
        "properties": {
          "cancel": {
            "type": "boolean",
            "enum": [
              true
            ],
            "description": "The collector accepts `POST /v1/kyc/session-cancel` for this session."
          },
          "emailVerification": {
            "type": "boolean",
            "enum": [
              true
            ],
            "description": "The hosted flow includes the email-verification step for this session."
          }
        }
      },
      "KycEmailVerificationMode": {
        "type": "string",
        "enum": [
          "off",
          "optional",
          "required"
        ],
        "description": "Hosted email-verification mode. `off` — no email step. `optional` — the customer is offered the step and may skip it. `required` — the customer must verify an address before the session can be submitted (`409 email_verification_required` until then). The mode is resolved once at mint and fixed for the session. On the tenant-facing `GET /v1/kyc/sessions/{sessionId}` this key is the effective mode string; the hosted page's own session routes carry the customer-facing state object `KycEmailVerificationState` under the same key."
      },
      "KycEmailVerificationState": {
        "type": "object",
        "description": "The customer-facing email-verification state returned by the hosted page's email routes and embedded in the snapshot as `emailVerification`. The address is always masked (`j***@example.com`).",
        "required": [
          "mode",
          "email",
          "verified",
          "verifiedAt",
          "expiresAt",
          "resendAvailableAt",
          "sendsRemaining"
        ],
        "properties": {
          "mode": {
            "type": "string",
            "enum": [
              "optional",
              "required"
            ]
          },
          "email": {
            "type": [
              "string",
              "null"
            ],
            "description": "The masked address; `null` before one was entered."
          },
          "verified": {
            "type": "boolean"
          },
          "verifiedAt": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          },
          "expiresAt": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "Deadline of the live confirmation link (30 minutes or the session end, whichever is sooner); `null` when none is live."
          },
          "resendAvailableAt": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "Earliest next send while the 60 second cooldown runs; `null` when a resend is allowed now or the cap is exhausted."
          },
          "sendsRemaining": {
            "type": "integer",
            "description": "Sends left of the 5 allowed per session."
          }
        }
      },
      "KycEmailVerificationStateEnvelope": {
        "type": "object",
        "description": "The body of the hosted page's email routes (`POST /v1/kyc/session-email/send`, `GET /v1/kyc/session-email/status`).",
        "required": [
          "emailVerification",
          "requestId"
        ],
        "properties": {
          "emailVerification": {
            "$ref": "#/components/schemas/KycEmailVerificationState"
          },
          "requestId": {
            "type": "string"
          }
        }
      },
      "KycVerificationIdStatus": {
        "type": "string",
        "enum": [
          "verified",
          "pending",
          "revoked",
          "expired"
        ],
        "description": "Public status of a Noxtica Verification ID. `revoked` wins over everything; `pending` = the verification awaits a review decision; `expired` = 365 days after completion; otherwise `verified`."
      },
      "KycVerificationIdentifier": {
        "type": "object",
        "description": "The session's Noxtica Verification ID as shown on the hosted page's final screen (`session.verificationIdentifier` on `GET /v1/kyc/session-view`). Customer-facing; never carries an address.",
        "required": [
          "nvid",
          "status",
          "verifiedAt",
          "expiresAt",
          "emailOnFile"
        ],
        "properties": {
          "nvid": {
            "type": "string",
            "description": "Canonical NVID, NVID-XXXX-XXXX-XXXX-XXXX."
          },
          "status": {
            "$ref": "#/components/schemas/KycVerificationIdStatus"
          },
          "verifiedAt": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "Unix ms of completion; `null` while pending."
          },
          "expiresAt": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "Unix ms, completion + 365 days; `null` while pending."
          },
          "emailOnFile": {
            "type": "boolean",
            "description": "Whether the person gave an address to receive the NVID. The address itself is never returned."
          }
        }
      },
      "KycVerificationIdEmailRequest": {
        "type": "object",
        "required": [
          "email",
          "locale",
          "consent"
        ],
        "properties": {
          "email": {
            "type": "string",
            "description": "The address to send the NVID to (normalised server-side).",
            "maxLength": 254
          },
          "locale": {
            "type": "string",
            "description": "One of the 36 supported UI locales; the email is rendered in it (unsupported falls back to `en`)."
          },
          "consent": {
            "type": "object",
            "required": [
              "version",
              "accepted"
            ],
            "properties": {
              "version": {
                "type": "string",
                "enum": [
                  "nvid-email-v1"
                ]
              },
              "accepted": {
                "type": "boolean",
                "enum": [
                  true
                ]
              }
            }
          }
        }
      },
      "KycVerificationIdStatusResponse": {
        "type": "object",
        "required": [
          "ok",
          "verification"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "verification": {
            "type": "object",
            "required": [
              "id",
              "status",
              "verifiedAt",
              "expiresAt",
              "revokedAt",
              "requestedBy"
            ],
            "properties": {
              "id": {
                "type": "string",
                "description": "Canonical NVID."
              },
              "status": {
                "$ref": "#/components/schemas/KycVerificationIdStatus"
              },
              "verifiedAt": {
                "type": [
                  "integer",
                  "null"
                ],
                "format": "int64",
                "description": "Unix ms of completion; `null` while pending."
              },
              "expiresAt": {
                "type": [
                  "integer",
                  "null"
                ],
                "format": "int64",
                "description": "Unix ms, completion + 365 days; `null` while pending."
              },
              "revokedAt": {
                "type": [
                  "integer",
                  "null"
                ],
                "format": "int64",
                "description": "Unix ms of the revocation; `null` unless revoked."
              },
              "requestedBy": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The requesting business's display name; `null` when none is configured."
              }
            }
          }
        }
      },
      "KycHostedSessionOptions": {
        "type": "object",
        "description": "Invitation-scoped hosted-flow switches, frozen into the session at mint. When you send `hostedOptions` it must be the complete object (every required key below, no merging with defaults); omit it to use the defaults (all four document types, `allowDeviceUpload` false, `documentBack` `auto`, `documentNearFace` false, `activeLiveness` true, `speechAnalysis` false, `ageGenderEstimation` false, `emailVerification` `off`). Inside `steps`, `ageGenderEstimation` and `emailVerification` are optional.",
        "required": [
          "allowedDocumentTypes",
          "allowDeviceUpload",
          "steps"
        ],
        "properties": {
          "allowedDocumentTypes": {
            "type": "array",
            "minItems": 1,
            "maxItems": 4,
            "uniqueItems": true,
            "items": {
              "type": "string",
              "enum": [
                "national_id",
                "passport",
                "driving_license",
                "residence_permit"
              ]
            }
          },
          "allowDeviceUpload": {
            "type": "boolean"
          },
          "steps": {
            "type": "object",
            "required": [
              "documentBack",
              "documentNearFace",
              "activeLiveness",
              "speechAnalysis"
            ],
            "properties": {
              "documentBack": {
                "type": "string",
                "enum": [
                  "auto"
                ]
              },
              "documentNearFace": {
                "type": "boolean"
              },
              "activeLiveness": {
                "type": "boolean"
              },
              "speechAnalysis": {
                "type": "boolean"
              },
              "ageGenderEstimation": {
                "type": "boolean",
                "description": "Optional; default `false`. Adds an advisory age and gender estimate from the selfie frames (biometric, special-category data); the customer gives a separate consent on the page. Setting `true` is refused with `403 age_gender_estimation_not_enabled` (`reasonCode` `age_gender_platform_disabled` or `age_gender_tenant_acknowledgement_missing`) unless the platform has enabled the feature AND your organisation has recorded the matching legal-basis acknowledgement in the Backoffice. It never fails a verification."
              },
              "emailVerification": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/KycEmailVerificationMode"
                  }
                ],
                "description": "Optional (added 2026-10-01; default `off` when the key is absent). When omitted from a mint request your organisation's default applies; an explicit value wins in both directions. An explicit `optional` or `required` is refused with `400 email_verification_unavailable` until the platform has enabled hosted email verification. The mint response echoes the effective mode."
              }
            }
          }
        }
      },
      "KycSessionCompletedWebhookData": {
        "type": "object",
        "description": "The `data` member of `kyc.session.completed` (`schemaVersion` `\"1\"`). Delivery is at-least-once: deduplicate by `deliveryId`. A webhook is a notification, not authority; read `GET /v1/kyc/sessions/{sessionId}` for the outcome. There is no subject reference, digest, evidence id or scorecard. The event does not fire when a session lands in `review_pending`; it fires when a reviewer's decision moves it to `completed`. `email` and `emailVerified` (added 2026-10-01, additive) are present only when hosted email verification is enabled for the platform AND the session has a stored address; otherwise both keys are absent.",
        "required": [
          "schemaVersion",
          "sessionId",
          "status",
          "verificationId",
          "reasonCodes",
          "occurredAt",
          "deliveryId"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "enum": [
              "1"
            ]
          },
          "sessionId": {
            "type": "string",
            "format": "uuid",
            "description": "The id the mint call returned."
          },
          "status": {
            "type": "string",
            "enum": [
              "completed",
              "unverified",
              "error"
            ],
            "description": "The terminal session status. `expired` and `cancelled_by_user` sessions never emit this event."
          },
          "verificationId": {
            "type": [
              "string",
              "null"
            ]
          },
          "reasonCodes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "occurredAt": {
            "type": "integer",
            "format": "int64",
            "description": "Unix ms the session reached this status (its `completedAt`)."
          },
          "deliveryId": {
            "type": "string"
          },
          "nvid": {
            "type": "string",
            "description": "The session's Noxtica Verification ID (`NVID-XXXX-XXXX-XXXX-XXXX`). Present only when the session has one (the feature is enabled for your organisation and the outcome was positive); otherwise absent. Never accompanied by the address the person may have given to receive it."
          },
          "email": {
            "type": "string",
            "description": "Present only when the session has a stored address (and hosted email verification is enabled for the platform). The normalised address the end customer entered in the hosted flow. Unverified unless `emailVerified` is `true`."
          },
          "emailVerified": {
            "type": "boolean",
            "description": "Present together with `email`. `true` only if the customer clicked the confirmation link for `email`."
          }
        }
      },
      "KycSessionCancelledWebhookData": {
        "type": "object",
        "description": "The `data` member of `kyc.session.cancelled` (`schemaVersion` `\"1\"`). Same delivery semantics as `KycSessionCompletedWebhookData`. `email` and `emailVerified` (added 2026-10-01, additive) are present only when hosted email verification is enabled for the platform AND the session has a stored address; otherwise both keys are absent.",
        "required": [
          "schemaVersion",
          "sessionId",
          "status",
          "cancelReason",
          "cancelledAt",
          "occurredAt",
          "deliveryId"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "enum": [
              "1"
            ]
          },
          "sessionId": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "enum": [
              "cancelled_by_user"
            ]
          },
          "cancelReason": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/KycSessionCancelReason"
              },
              {
                "type": "null"
              }
            ]
          },
          "cancelledAt": {
            "type": "integer",
            "format": "int64",
            "description": "Unix ms."
          },
          "occurredAt": {
            "type": "integer",
            "format": "int64",
            "description": "Unix ms; equal to `cancelledAt`."
          },
          "deliveryId": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "description": "Present only when the session has a stored address (and hosted email verification is enabled for the platform). The normalised address the end customer entered before cancelling. Unverified unless `emailVerified` is `true`."
          },
          "emailVerified": {
            "type": "boolean",
            "description": "Present together with `email`. `true` only if the customer clicked the confirmation link for `email`."
          }
        }
      },
      "KycVerificationCompletedWebhookData": {
        "type": "object",
        "description": "The `data` member of `kyc.verification.completed` (`schemaVersion` `\"1\"`). A closed, non-personal field set: no subject id, digest or document value. Deduplicate by `deliveryId`; read the verification through the API before acting.",
        "required": [
          "schemaVersion",
          "verificationId",
          "verdict",
          "reasonCodes",
          "idType",
          "occurredAt",
          "deliveryId"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "enum": [
              "1"
            ]
          },
          "verificationId": {
            "type": "string"
          },
          "verdict": {
            "type": "string",
            "enum": [
              "verified",
              "unverified",
              "error"
            ]
          },
          "reasonCodes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Closed reason-code catalog; may be empty."
          },
          "idType": {
            "type": "string",
            "description": "The document type asserted on the request, e.g. `passport`."
          },
          "occurredAt": {
            "type": "integer",
            "format": "int64",
            "description": "Unix ms the verification reached its terminal state."
          },
          "deliveryId": {
            "type": "string"
          }
        }
      },
      "KycErasureCompletedWebhookData": {
        "type": "object",
        "description": "The `data` member of `kyc.erasure.completed` (`schemaVersion` `\"1\"`). Emitted only when the erasure request reaches `completed`; a `partial` erasure emits nothing. No subject identifier is carried.",
        "required": [
          "schemaVersion",
          "requestId",
          "outcome",
          "occurredAt",
          "deliveryId"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "enum": [
              "1"
            ]
          },
          "requestId": {
            "type": "string",
            "description": "The erasure request's own id; not a subject id."
          },
          "outcome": {
            "type": "string",
            "enum": [
              "completed"
            ]
          },
          "occurredAt": {
            "type": "integer",
            "format": "int64",
            "description": "Unix ms the erasure request reached its terminal state."
          },
          "deliveryId": {
            "type": "string"
          }
        }
      },
      "KycDocumentExpiryWarningWebhookData": {
        "type": "object",
        "description": "The `data` member of `kyc.document.expiry_warning` (`schemaVersion` `\"1\"`). No subject id and no document number: correlate by `verificationId`.",
        "required": [
          "schemaVersion",
          "verificationId",
          "alertType",
          "documentExpiresAt",
          "occurredAt",
          "deliveryId"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "enum": [
              "1"
            ]
          },
          "verificationId": {
            "type": "string"
          },
          "alertType": {
            "type": "string",
            "enum": [
              "expiry_90d",
              "expiry_60d",
              "expiry_30d",
              "expiry_expired"
            ]
          },
          "documentExpiresAt": {
            "type": "integer",
            "format": "int64",
            "description": "Unix ms the monitored document expires (or expired)."
          },
          "occurredAt": {
            "type": "integer",
            "format": "int64",
            "description": "Unix ms the threshold crossing was detected."
          },
          "deliveryId": {
            "type": "string"
          }
        }
      },
      "KycReverificationDueWebhookData": {
        "type": "object",
        "description": "The `data` member of `kyc.reverification.due` (`schemaVersion` `\"1\"`). No subject id.",
        "required": [
          "schemaVersion",
          "verificationId",
          "dueAt",
          "occurredAt",
          "deliveryId"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "enum": [
              "1"
            ]
          },
          "verificationId": {
            "type": "string"
          },
          "dueAt": {
            "type": "integer",
            "format": "int64",
            "description": "Unix ms the re-verification became due."
          },
          "occurredAt": {
            "type": "integer",
            "format": "int64"
          },
          "deliveryId": {
            "type": "string"
          }
        }
      },
      "KycSessionCompletedWebhookEvent": {
        "type": "object",
        "description": "The JSON body of a `kyc.session.completed` delivery. Keys are in the order shown.",
        "required": [
          "id",
          "type",
          "created_at",
          "tenant_id",
          "data"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "The delivery id, `<sessionId>:<webhookId>`. Identical on every retry; equals `X-Noxtica-Delivery` and `data.deliveryId`."
          },
          "type": {
            "type": "string",
            "enum": [
              "kyc.session.completed"
            ]
          },
          "created_at": {
            "type": "integer",
            "format": "int64",
            "description": "Unix ms the event occurred."
          },
          "tenant_id": {
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/KycSessionCompletedWebhookData"
          }
        }
      },
      "KycSessionCancelledWebhookEvent": {
        "type": "object",
        "description": "The JSON body of a `kyc.session.cancelled` delivery.",
        "required": [
          "id",
          "type",
          "created_at",
          "tenant_id",
          "data"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "The delivery id, `<sessionId>:<webhookId>`."
          },
          "type": {
            "type": "string",
            "enum": [
              "kyc.session.cancelled"
            ]
          },
          "created_at": {
            "type": "integer",
            "format": "int64",
            "description": "Unix ms the event occurred."
          },
          "tenant_id": {
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/KycSessionCancelledWebhookData"
          }
        }
      },
      "KycVerificationCompletedWebhookEvent": {
        "type": "object",
        "description": "The JSON body of a `kyc.verification.completed` delivery.",
        "required": [
          "id",
          "type",
          "created_at",
          "tenant_id",
          "data"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "The delivery id, `<verificationId>:<webhookId>`."
          },
          "type": {
            "type": "string",
            "enum": [
              "kyc.verification.completed"
            ]
          },
          "created_at": {
            "type": "integer",
            "format": "int64",
            "description": "Unix ms the event occurred."
          },
          "tenant_id": {
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/KycVerificationCompletedWebhookData"
          }
        }
      },
      "KycErasureCompletedWebhookEvent": {
        "type": "object",
        "description": "The JSON body of a `kyc.erasure.completed` delivery.",
        "required": [
          "id",
          "type",
          "created_at",
          "tenant_id",
          "data"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "The delivery id; equals `data.deliveryId`."
          },
          "type": {
            "type": "string",
            "enum": [
              "kyc.erasure.completed"
            ]
          },
          "created_at": {
            "type": "integer",
            "format": "int64",
            "description": "Unix ms the event occurred."
          },
          "tenant_id": {
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/KycErasureCompletedWebhookData"
          }
        }
      },
      "KycDocumentExpiryWarningWebhookEvent": {
        "type": "object",
        "description": "The JSON body of a `kyc.document.expiry_warning` delivery.",
        "required": [
          "id",
          "type",
          "created_at",
          "tenant_id",
          "data"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "The delivery id; equals `data.deliveryId`."
          },
          "type": {
            "type": "string",
            "enum": [
              "kyc.document.expiry_warning"
            ]
          },
          "created_at": {
            "type": "integer",
            "format": "int64",
            "description": "Unix ms the event occurred."
          },
          "tenant_id": {
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/KycDocumentExpiryWarningWebhookData"
          }
        }
      },
      "KycReverificationDueWebhookEvent": {
        "type": "object",
        "description": "The JSON body of a `kyc.reverification.due` delivery.",
        "required": [
          "id",
          "type",
          "created_at",
          "tenant_id",
          "data"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "The delivery id; equals `data.deliveryId`."
          },
          "type": {
            "type": "string",
            "enum": [
              "kyc.reverification.due"
            ]
          },
          "created_at": {
            "type": "integer",
            "format": "int64",
            "description": "Unix ms the event occurred."
          },
          "tenant_id": {
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/KycReverificationDueWebhookData"
          }
        }
      },
      "KycSessionCancelReason": {
        "type": "string",
        "description": "The closed set of reasons an end customer may give when cancelling a hosted session. There is deliberately no free-text reason.",
        "enum": [
          "not_now",
          "privacy_concern",
          "no_document",
          "technical_problem",
          "other"
        ]
      },
      "KycSessionCancelRequest": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "reason": {
            "$ref": "#/components/schemas/KycSessionCancelReason"
          }
        }
      },
      "KycSessionCancelResponse": {
        "type": "object",
        "required": [
          "ok",
          "status",
          "cancelledAt",
          "cancelReason",
          "requestId"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "cancelled_by_user"
            ]
          },
          "cancelledAt": {
            "type": "integer",
            "format": "int64",
            "description": "Unix ms of the cancel. An idempotent replay returns the ORIGINAL value, never a fresh timestamp."
          },
          "cancelReason": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/KycSessionCancelReason"
              },
              {
                "type": "null"
              }
            ],
            "description": "The reason recorded by the FIRST successful call (`null` if none was given). A replay returns the original reason."
          },
          "requestId": {
            "type": "string"
          }
        }
      },
      "KycSessionNotCancellableError": {
        "type": "object",
        "required": [
          "error",
          "status",
          "requestId"
        ],
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "session_not_cancellable"
            ]
          },
          "status": {
            "type": "string",
            "description": "The session's current status, which is why it cannot be cancelled (`verifying`, `completed`, `unverified`, `error`, or `review_pending`)."
          },
          "requestId": {
            "type": "string"
          }
        }
      },
      "KycSessionCancelledError": {
        "type": "object",
        "description": "The byte-identical 410 envelope every session-scoped KYC customer route (session-view/session-progress/session-submit/session-evidence/handle/ session-evidence/finalize) returns for a session the end customer cancelled (`cancelled_by_user`). The mirror of `KycSessionExpiredError`; never returned by the tenant-facing `GET /v1/kyc/sessions/{sessionId}` status read, which stays 200 with the `cancelled_by_user` status.",
        "required": [
          "error",
          "code",
          "requestId"
        ],
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "session_cancelled"
            ]
          },
          "code": {
            "type": "string",
            "enum": [
              "kyc_session_cancelled"
            ]
          },
          "requestId": {
            "type": "string"
          }
        }
      },
      "KycSessionExpiredError": {
        "type": "object",
        "description": "The byte-identical 410 envelope every session-scoped KYC customer route (session-view/session-progress/session-submit/session-evidence/handle/ session-evidence/finalize) returns for an expired, non-terminal session (KycSessionTtl, 2026-09-27 owner directive) — never returned by the tenant-facing `GET /v1/kyc/sessions/{sessionId}` status read, which stays 200 with an effective `status` of `expired` instead.",
        "required": [
          "error",
          "code",
          "requestId"
        ],
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "session_expired"
            ]
          },
          "code": {
            "type": "string",
            "enum": [
              "kyc_session_expired"
            ]
          },
          "requestId": {
            "type": "string"
          }
        }
      },
      "JsonRpcRequest": {
        "type": "object",
        "required": [
          "jsonrpc",
          "method"
        ],
        "properties": {
          "jsonrpc": {
            "type": "string",
            "enum": [
              "2.0"
            ]
          },
          "id": {
            "type": [
              "string",
              "integer",
              "null"
            ],
            "description": "Echoed in the response. Omit only for requests where you do not need the answer correlated."
          },
          "method": {
            "type": "string",
            "description": "One of `initialize`, `tools/list`, `tools/call`, `resources/list`, `resources/templates/list`, `resources/read`."
          },
          "params": {
            "type": "object",
            "description": "Method parameters. `tools/call` takes `{name, arguments}`; `resources/read` takes `{uri}`; `initialize` may carry `protocolVersion`."
          }
        }
      },
      "JsonRpcResponse": {
        "type": "object",
        "required": [
          "jsonrpc",
          "id"
        ],
        "properties": {
          "jsonrpc": {
            "type": "string",
            "enum": [
              "2.0"
            ]
          },
          "id": {
            "type": [
              "string",
              "integer",
              "null"
            ]
          },
          "result": {
            "description": "Present on success. For `tools/call`: `{content: [{type: \"text\", text: \"<JSON>\"}], isError: false}`. For `tools/list`: `{tools: [...]}`. For `initialize`: `{protocolVersion, serverInfo, capabilities}`."
          },
          "error": {
            "$ref": "#/components/schemas/JsonRpcError"
          }
        }
      },
      "JsonRpcError": {
        "type": "object",
        "required": [
          "code",
          "message"
        ],
        "description": "`code` values: `-32700` the body is not valid JSON; `-32600` no `method`; `-32601` unknown\nmethod; `-32602` invalid parameters, or the result exceeds 200 KB; `-32603` the tool or\nresource failed; `-32001` the token's scopes or tool list do not allow the tool\n(`data.requiredScope` names the missing scope); `-32002` tool not found for this token;\n`-32003` the monthly query allowance is used up; `-32004` too many tool calls\n(`data.retryAfterSeconds`, `data.limit`, `data.windowSeconds`); `-32005` MCP is not\nincluded in the plan; `-32006` resource not found.",
        "properties": {
          "code": {
            "type": "integer",
            "enum": [
              -32700,
              -32600,
              -32601,
              -32602,
              -32603,
              -32001,
              -32002,
              -32003,
              -32004,
              -32005,
              -32006
            ]
          },
          "message": {
            "type": "string"
          },
          "data": {
            "type": "object",
            "description": "Optional structured detail, for example `requiredScope` or `retryAfterSeconds`.",
            "properties": {
              "requiredScope": {
                "type": "string"
              },
              "retryAfterSeconds": {
                "type": "integer"
              },
              "limit": {
                "type": "integer"
              },
              "windowSeconds": {
                "type": "integer"
              },
              "code": {
                "type": "string"
              }
            }
          }
        }
      },
      "McpHttpError": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "unauthorized",
              "not_found",
              "rate_limited",
              "internal_error"
            ]
          }
        }
      },
      "ApiError": {
        "type": "object",
        "required": [
          "code",
          "error"
        ],
        "properties": {
          "code": {
            "type": "string",
            "description": "Stable machine-readable identifier."
          },
          "error": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "requestId": {
            "type": "string"
          }
        }
      },
      "AttestationReasonCode": {
        "type": "string",
        "enum": [
          "ok",
          "ek_chain_unverified",
          "no_policy",
          "tpm_unavailable",
          "base_level_below_l2",
          "platform_unsupported",
          "quote_signature_invalid",
          "quote_not_a_quote",
          "quote_nonce_mismatch",
          "ak_attributes_invalid",
          "pcr_select_mismatch",
          "pcr_digest_mismatch",
          "pcr_not_in_policy",
          "certify_signature_invalid",
          "certify_not_a_certify",
          "certify_nonce_mismatch",
          "certify_name_mismatch",
          "posture_secure_boot_required",
          "posture_lockdown_below_min",
          "posture_ima_required",
          "posture_dm_verity_required",
          "attestation_stale",
          "attestation_withdrawn",
          "policy_revised"
        ],
        "description": "Closed reason codes of an attestation verdict. `ok` + `ek_chain_unverified` accompany every L3."
      },
      "TenantAttestation": {
        "type": "object",
        "required": [
          "level",
          "reasonCodes",
          "attestedAt",
          "expiresAt",
          "policyRevision"
        ],
        "description": "DET-1, additive. The attestation facts of the active enrolment with the highest EFFECTIVE level (ties: most recent statement). No posture values and no PCR values. The level is the effective one: an L3 past its expiry reads as its base level with `attestation_stale`.",
        "properties": {
          "level": {
            "type": "string",
            "enum": [
              "L0",
              "L1",
              "L2",
              "L3"
            ]
          },
          "reasonCodes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AttestationReasonCode"
            }
          },
          "attestedAt": {
            "oneOf": [
              {
                "type": "integer",
                "format": "int64"
              },
              {
                "type": "null"
              }
            ]
          },
          "expiresAt": {
            "oneOf": [
              {
                "type": "integer",
                "format": "int64"
              },
              {
                "type": "null"
              }
            ]
          },
          "policyRevision": {
            "oneOf": [
              {
                "type": "integer",
                "minimum": 1
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "TenantSubjectStatus": {
        "type": "object",
        "description": "A `psub_…` subject always carries every member. A subject resolved through a LINK carries `scopes` and only the members of the scopes the player granted (`status`: `enrolled` + `revokedAt`/`reasonCode`; `attestation_level`: `deviceAttestationLevel` + `attestation`; `last_seen`: `lastSeen`; `open_signals`: `openSignals`).",
        "required": [
          "schemaVersion",
          "subject"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "const": "pulse.tenant.subject-status/v1"
          },
          "scopes": {
            "type": "array",
            "description": "Present only for a subject resolved through a link: the scopes the player granted.",
            "items": {
              "$ref": "#/components/schemas/LinkScope"
            }
          },
          "subject": {
            "type": "string",
            "description": "The subject exactly as asked."
          },
          "enrolled": {
            "type": "boolean",
            "description": "At least one active enrolment."
          },
          "deviceAttestationLevel": {
            "description": "Highest attestation level among the active enrolments; `null` when not enrolled.",
            "oneOf": [
              {
                "type": "string",
                "enum": [
                  "L0",
                  "L1",
                  "L2",
                  "L3"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "attestation": {
            "description": "DET-1, additive (same `attestation_level` link scope as `deviceAttestationLevel`). The attestation facts of the best active enrolment; `null` when it never attested; absent when the subject is not enrolled.",
            "oneOf": [
              {
                "$ref": "#/components/schemas/TenantAttestation"
              },
              {
                "type": "null"
              }
            ]
          },
          "lastSeen": {
            "description": "Latest control-plane activity (epoch ms) of any enrolment of the subject, `null` when never.",
            "oneOf": [
              {
                "type": "integer",
                "format": "int64"
              },
              {
                "type": "null"
              }
            ]
          },
          "openSignals": {
            "type": "array",
            "maxItems": 50,
            "items": {
              "$ref": "#/components/schemas/TenantOpenSignal"
            }
          },
          "responseHints": {
            "type": "array",
            "description": "Additive. The subject's ACTIVE response hints (an executed `suspend_session_hint` that passed the server's Art. 22 gate, not reversed, not expired), newest first; `[]` when there are none. Never a dry run, a suppressed action or a notice. A hint is a signal for the tenant's own decision. For a link subject present only when the player granted `open_signals`.",
            "items": {
              "$ref": "#/components/schemas/TenantResponseHint"
            }
          },
          "revokedAt": {
            "type": "integer",
            "format": "int64",
            "description": "Present only when `enrolled` is false."
          },
          "reasonCode": {
            "type": "string",
            "description": "Present only when `enrolled` is false; the closed revocation reason (e.g. `player_removed`, `tenant_revoked`, `refresh_reuse`)."
          }
        }
      },
      "ResponseAction": {
        "type": "string",
        "enum": [
          "notify_user",
          "suspend_session_hint"
        ],
        "description": "The closed local-action allow-list of the response executor. Nothing else is representable."
      },
      "ResponseOutcome": {
        "type": "string",
        "enum": [
          "executed",
          "dry_run",
          "suppressed_rate_limit",
          "suppressed_cooldown",
          "suppressed_kill_switch",
          "suppressed_requires_human"
        ]
      },
      "TenantDecisionList": {
        "type": "object",
        "required": [
          "schemaVersion",
          "decisions",
          "nextCursor"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "const": "pulse.tenant.decisions/v1"
          },
          "decisions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TenantDecision"
            }
          },
          "nextCursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Opaque; `null` on the last page."
          }
        }
      },
      "TenantDecision": {
        "type": "object",
        "required": [
          "schemaVersion",
          "id",
          "appId",
          "subject",
          "action",
          "outcome",
          "reason",
          "reasonCode",
          "severity",
          "evidenceTier",
          "ruleId",
          "ladderId",
          "bundleRevision",
          "observedAt",
          "recordedAt",
          "detection",
          "hint"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "const": "pulse.tenant.decision/v1"
          },
          "id": {
            "type": "string",
            "pattern": "^pact_[0-7][0-9A-HJKMNP-TV-Z]{25}$"
          },
          "appId": {
            "type": "string"
          },
          "subject": {
            "type": "object",
            "required": [
              "psub",
              "deviceRef"
            ],
            "properties": {
              "psub": {
                "type": "string"
              },
              "deviceRef": {
                "type": "string"
              }
            }
          },
          "action": {
            "$ref": "#/components/schemas/ResponseAction"
          },
          "outcome": {
            "allOf": [
              {
                "$ref": "#/components/schemas/ResponseOutcome"
              }
            ],
            "description": "The outcome of record after the server's gates (a report the server downgraded reads `suppressed_kill_switch`, `suppressed_requires_human` or `dry_run`)."
          },
          "reason": {
            "type": "string"
          },
          "reasonCode": {
            "type": "string"
          },
          "severity": {
            "type": "string",
            "enum": [
              "low",
              "medium",
              "high",
              "critical"
            ]
          },
          "evidenceTier": {
            "type": "string",
            "enum": [
              "t0",
              "t1"
            ]
          },
          "ruleId": {
            "type": "string"
          },
          "ladderId": {
            "type": "string"
          },
          "bundleRevision": {
            "type": "integer"
          },
          "observedAt": {
            "type": "integer",
            "format": "int64"
          },
          "recordedAt": {
            "type": "integer",
            "format": "int64"
          },
          "detection": {
            "description": "The detection the decision answers; `status` and `appealState` are `null` while its event has not been ingested.",
            "oneOf": [
              {
                "type": "object",
                "required": [
                  "id",
                  "status",
                  "appealState"
                ],
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "status": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "enum": [
                      "open",
                      "under_review",
                      "confirmed",
                      "dismissed",
                      "overturned",
                      "suppressed",
                      null
                    ]
                  },
                  "appealState": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "enum": [
                      "none",
                      "open",
                      "upheld",
                      "overturned",
                      "withdrawn",
                      null
                    ]
                  }
                }
              },
              {
                "type": "null"
              }
            ]
          },
          "hint": {
            "description": "`null` when the decision produced no hint.",
            "oneOf": [
              {
                "type": "object",
                "required": [
                  "state",
                  "issuedAt",
                  "expiresAt",
                  "reversedAt",
                  "reversalSource",
                  "reversalReasonCode"
                ],
                "properties": {
                  "state": {
                    "type": "string",
                    "enum": [
                      "active",
                      "expired",
                      "reversed"
                    ]
                  },
                  "issuedAt": {
                    "type": "integer",
                    "format": "int64",
                    "description": "When the hint began: `min(observed_at, recorded_at)` — never later than the server saw the report. Equals `responseHints[].issuedAt` of the subject status."
                  },
                  "expiresAt": {
                    "type": "integer",
                    "format": "int64"
                  },
                  "reversedAt": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "format": "int64"
                  },
                  "reversalSource": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "enum": [
                      "staff",
                      "tenant_api",
                      "appeal_overturned",
                      "detection_dismissed",
                      "detection_overturned",
                      "detection_suppressed",
                      null
                    ]
                  },
                  "reversalReasonCode": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "enum": [
                      "handled",
                      "false_positive",
                      "account_verified",
                      "policy_exception",
                      "other",
                      null
                    ]
                  }
                }
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "TenantResponseHint": {
        "type": "object",
        "required": [
          "decisionId",
          "action",
          "reasonCode",
          "severity",
          "issuedAt",
          "expiresAt"
        ],
        "properties": {
          "decisionId": {
            "type": "string",
            "description": "The `pact_…` id of the decision (`GET /pulse/v1/tenant/decisions/{id}`)."
          },
          "action": {
            "type": "string",
            "const": "suspend_session_hint"
          },
          "reasonCode": {
            "type": "string"
          },
          "severity": {
            "type": "string",
            "enum": [
              "low",
              "medium",
              "high",
              "critical"
            ]
          },
          "issuedAt": {
            "type": "integer",
            "format": "int64",
            "description": "When the hint began: `min(observed_at, recorded_at)` of the decision (equals `hint.issuedAt` of `GET /pulse/v1/tenant/decisions/{id}`)."
          },
          "expiresAt": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "LinkScope": {
        "type": "string",
        "enum": [
          "status",
          "attestation_level",
          "last_seen",
          "open_signals"
        ],
        "description": "What a tenant may see of a linked player. The consent screen requests all four."
      },
      "LinkUnlinkedBy": {
        "type": "string",
        "enum": [
          "player",
          "tenant",
          "platform",
          "account_deleted"
        ]
      },
      "TenantLinkCodeRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "externalUserId",
          "appId"
        ],
        "properties": {
          "externalUserId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256,
            "description": "The tenant's own user id. No leading/trailing whitespace, no control characters."
          },
          "appId": {
            "type": "string",
            "pattern": "^[A-Za-z0-9_.:-]{1,64}$",
            "description": "An ACTIVE application of this tenant."
          },
          "locale": {
            "type": "string",
            "maxLength": 35,
            "description": "BCP 47 tag appended to the `url` so the consent screen opens in the person's language."
          }
        }
      },
      "TenantLinkCode": {
        "type": "object",
        "required": [
          "code",
          "expiresAt",
          "url"
        ],
        "properties": {
          "code": {
            "type": "string",
            "pattern": "^pl_[A-Za-z0-9_-]{32}$",
            "description": "Shown once; single use."
          },
          "expiresAt": {
            "type": "integer",
            "format": "int64",
            "description": "Epoch ms; 10 minutes after issue."
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "`{app origin}/link?code=…[&locale=…]` — the page the person opens."
          }
        }
      },
      "TenantLink": {
        "type": "object",
        "required": [
          "schemaVersion",
          "subject",
          "externalUserId",
          "applicationId",
          "state",
          "scopes",
          "linkedAt",
          "unlinkedAt",
          "unlinkedBy"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "const": "pulse.tenant.link/v1"
          },
          "subject": {
            "type": "string",
            "pattern": "^plnk_[0-9A-HJKMNP-TV-Z]{26}$",
            "description": "The pairwise subject: random per link, never derived from the account."
          },
          "externalUserId": {
            "type": "string"
          },
          "applicationId": {
            "type": "string"
          },
          "state": {
            "type": "string",
            "enum": [
              "active",
              "unlinked"
            ]
          },
          "scopes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LinkScope"
            }
          },
          "linkedAt": {
            "type": "integer",
            "format": "int64"
          },
          "unlinkedAt": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64"
          },
          "unlinkedBy": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/LinkUnlinkedBy"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "TenantLinkUnlinked": {
        "allOf": [
          {
            "$ref": "#/components/schemas/TenantLink"
          },
          {
            "type": "object",
            "required": [
              "changed"
            ],
            "properties": {
              "changed": {
                "type": "boolean",
                "description": "`false` when the link was already unlinked (nothing written)."
              }
            }
          }
        ]
      },
      "TenantOpenSignal": {
        "type": "object",
        "required": [
          "reasonCode",
          "severity",
          "tier",
          "status",
          "detectedAt"
        ],
        "properties": {
          "reasonCode": {
            "type": "string",
            "pattern": "^[A-Z]{3}-[0-9]{3}$"
          },
          "severity": {
            "type": "string",
            "enum": [
              "low",
              "medium",
              "high",
              "critical"
            ]
          },
          "tier": {
            "type": "string",
            "enum": [
              "t0",
              "t1",
              "t2"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "open",
              "under_review"
            ]
          },
          "detectedAt": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "ProtectedActionVerifyError": {
        "type": "object",
        "required": [
          "ok",
          "error",
          "requestId"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "enum": [
              false
            ]
          },
          "error": {
            "type": "string",
            "enum": [
              "invalid_body",
              "invalid_request_id",
              "invalid_action",
              "invalid_expected_domain",
              "payload_too_large",
              "request_not_found",
              "already_consumed",
              "action_mismatch",
              "domain_mismatch"
            ]
          },
          "consumed": {
            "type": "boolean",
            "description": "Present on `already_consumed`."
          },
          "consumedAt": {
            "type": "string",
            "format": "date-time",
            "description": "Present on `already_consumed`."
          },
          "requestId": {
            "type": "string",
            "description": "The collector's own correlation id for this call."
          }
        }
      },
      "ApmScopedId": {
        "type": "string",
        "minLength": 1,
        "maxLength": 128,
        "pattern": "^[A-Za-z0-9._:-]+$"
      },
      "ApmError": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "error",
          "requestId"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "const": false
          },
          "error": {
            "type": "string"
          },
          "reason": {
            "type": "string"
          },
          "requestId": {
            "type": "string"
          }
        }
      },
      "ApmRateLimitError": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "error",
          "retryAfter",
          "requestId"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "const": false
          },
          "error": {
            "type": "string"
          },
          "retryAfter": {
            "type": "integer",
            "minimum": 1
          },
          "requestId": {
            "type": "string"
          }
        }
      },
      "ApmUnavailable": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "available",
          "reason",
          "requestId"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "const": false
          },
          "available": {
            "type": "boolean",
            "const": false
          },
          "reason": {
            "type": "string"
          },
          "requestId": {
            "type": "string"
          }
        }
      },
      "ApmConflict": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "ok",
          "error",
          "requestId"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "const": false
          },
          "error": {
            "type": "string",
            "enum": [
              "capture_unavailable",
              "authority_epoch_conflict"
            ]
          },
          "available": {
            "type": "boolean",
            "const": false
          },
          "reason": {
            "type": "string",
            "enum": [
              "capture_rollout_disabled"
            ]
          },
          "expected_authority_epoch": {
            "type": "integer",
            "minimum": 1
          },
          "actual_authority_epoch": {
            "type": "integer",
            "minimum": 1
          },
          "requestId": {
            "type": "string"
          }
        }
      },
      "ApmGrantUnavailable": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "ok",
          "available",
          "reason",
          "state",
          "requestId"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "const": false
          },
          "available": {
            "type": "boolean",
            "const": false
          },
          "reason": {
            "type": "string",
            "enum": [
              "export_not_ready",
              "export_expired",
              "export_failed",
              "download_signing_unavailable"
            ]
          },
          "state": {
            "type": "string"
          },
          "requestId": {
            "type": "string"
          }
        }
      },
      "ApmProject": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "project_id",
          "display_name",
          "state",
          "region_id",
          "data_plane_id",
          "capture_enabled",
          "enabled_signals",
          "authority_epoch",
          "erasure_epoch",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "project_id": {
            "$ref": "#/components/schemas/ApmScopedId"
          },
          "display_name": {
            "type": "string"
          },
          "state": {
            "type": "string"
          },
          "region_id": {
            "type": "string"
          },
          "data_plane_id": {
            "type": "string"
          },
          "capture_enabled": {
            "type": "boolean"
          },
          "enabled_signals": {
            "type": "array",
            "maxItems": 2,
            "uniqueItems": true,
            "items": {
              "type": "string",
              "enum": [
                "traces",
                "rum_events"
              ]
            }
          },
          "authority_epoch": {
            "type": "integer",
            "minimum": 0
          },
          "erasure_epoch": {
            "type": "integer",
            "minimum": 0
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ApmEnvironmentPolicy": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "project_id",
          "environment_id",
          "display_name",
          "environment_kind",
          "state",
          "region_id",
          "data_plane_id",
          "capture_enabled",
          "allowed_signals",
          "sampling_policy_id",
          "retention_policy_version",
          "privacy_policy_version",
          "authority_epoch",
          "erasure_epoch",
          "quota_manifest_revision",
          "parser_manifest_revision",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "project_id": {
            "$ref": "#/components/schemas/ApmScopedId"
          },
          "environment_id": {
            "$ref": "#/components/schemas/ApmScopedId"
          },
          "display_name": {
            "type": "string"
          },
          "environment_kind": {
            "type": "string"
          },
          "state": {
            "type": "string"
          },
          "region_id": {
            "type": "string"
          },
          "data_plane_id": {
            "type": "string"
          },
          "capture_enabled": {
            "type": "boolean"
          },
          "allowed_signals": {
            "type": "array",
            "maxItems": 2,
            "uniqueItems": true,
            "items": {
              "type": "string",
              "enum": [
                "traces",
                "rum_events"
              ]
            }
          },
          "sampling_policy_id": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/ApmScopedId"
              },
              {
                "type": "null"
              }
            ]
          },
          "retention_policy_version": {
            "type": "integer",
            "minimum": 1
          },
          "privacy_policy_version": {
            "type": "integer",
            "minimum": 1
          },
          "authority_epoch": {
            "type": "integer",
            "minimum": 0
          },
          "erasure_epoch": {
            "type": "integer",
            "minimum": 0
          },
          "quota_manifest_revision": {
            "type": "integer",
            "minimum": 0
          },
          "parser_manifest_revision": {
            "type": "integer",
            "minimum": 0
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ApmProjectList": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "ok",
          "items",
          "count",
          "truncated",
          "next_cursor",
          "freshness",
          "completeness"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "const": true
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ApmProject"
            }
          },
          "count": {
            "type": "integer",
            "minimum": 0,
            "maximum": 200
          },
          "truncated": {
            "type": "boolean"
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ]
          },
          "freshness": {
            "type": "string",
            "const": "postgres_authority"
          },
          "completeness": {
            "type": "string",
            "enum": [
              "complete",
              "truncated"
            ]
          }
        }
      },
      "ApmEnvironmentList": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "ok",
          "project_id",
          "items",
          "count",
          "truncated",
          "next_cursor",
          "freshness",
          "completeness"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "const": true
          },
          "project_id": {
            "$ref": "#/components/schemas/ApmScopedId"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ApmEnvironmentPolicy"
            }
          },
          "count": {
            "type": "integer",
            "minimum": 0,
            "maximum": 200
          },
          "truncated": {
            "type": "boolean"
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ]
          },
          "freshness": {
            "type": "string",
            "const": "postgres_authority"
          },
          "completeness": {
            "type": "string",
            "enum": [
              "complete",
              "truncated"
            ]
          }
        }
      },
      "ApmSamplingPolicy": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "policy_id",
          "policy_version",
          "signal",
          "schema_version",
          "sampling_class",
          "mode",
          "enabled",
          "rate_ppm",
          "tail_window_seconds",
          "tail_budget_events",
          "effective_from",
          "effective_until"
        ],
        "properties": {
          "policy_id": {
            "type": "string"
          },
          "policy_version": {
            "type": "integer"
          },
          "signal": {
            "type": "string"
          },
          "schema_version": {
            "type": "integer"
          },
          "sampling_class": {
            "type": "string"
          },
          "mode": {
            "type": "string"
          },
          "enabled": {
            "type": "boolean"
          },
          "rate_ppm": {
            "type": [
              "integer",
              "null"
            ]
          },
          "tail_window_seconds": {
            "type": [
              "integer",
              "null"
            ]
          },
          "tail_budget_events": {
            "type": [
              "integer",
              "null"
            ]
          },
          "effective_from": {
            "type": "string",
            "format": "date-time"
          },
          "effective_until": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "ApmRetentionPolicy": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "signal",
          "retention_class",
          "policy_version",
          "duration_seconds",
          "minimum_seconds",
          "maximum_seconds",
          "region_id",
          "deletion_mode",
          "legal_hold_state",
          "enabled",
          "effective_from",
          "effective_until"
        ],
        "properties": {
          "signal": {
            "type": "string"
          },
          "retention_class": {
            "type": "string"
          },
          "policy_version": {
            "type": "integer"
          },
          "duration_seconds": {
            "type": [
              "integer",
              "null"
            ]
          },
          "minimum_seconds": {
            "type": "integer"
          },
          "maximum_seconds": {
            "type": "integer"
          },
          "region_id": {
            "type": "string"
          },
          "deletion_mode": {
            "type": "string"
          },
          "legal_hold_state": {
            "type": "string"
          },
          "enabled": {
            "type": "boolean"
          },
          "effective_from": {
            "type": "string",
            "format": "date-time"
          },
          "effective_until": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "ApmAuthorityFreshness": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "source",
          "updated_at"
        ],
        "properties": {
          "source": {
            "type": "string",
            "const": "postgres_authority"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ApmPolicySnapshot": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "ok",
          "project_id",
          "environment_id",
          "policy",
          "sampling_policies",
          "sampling_policy_count",
          "sampling_policies_truncated",
          "retention_policies",
          "retention_policy_count",
          "retention_policies_truncated",
          "freshness",
          "completeness"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "const": true
          },
          "project_id": {
            "$ref": "#/components/schemas/ApmScopedId"
          },
          "environment_id": {
            "$ref": "#/components/schemas/ApmScopedId"
          },
          "policy": {
            "$ref": "#/components/schemas/ApmEnvironmentPolicy"
          },
          "sampling_policies": {
            "type": "array",
            "maxItems": 100,
            "items": {
              "$ref": "#/components/schemas/ApmSamplingPolicy"
            }
          },
          "sampling_policy_count": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100
          },
          "sampling_policies_truncated": {
            "type": "boolean"
          },
          "retention_policies": {
            "type": "array",
            "maxItems": 100,
            "items": {
              "$ref": "#/components/schemas/ApmRetentionPolicy"
            }
          },
          "retention_policy_count": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100
          },
          "retention_policies_truncated": {
            "type": "boolean"
          },
          "freshness": {
            "$ref": "#/components/schemas/ApmAuthorityFreshness"
          },
          "completeness": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "sampling_policies",
              "retention_policies"
            ],
            "properties": {
              "sampling_policies": {
                "type": "string",
                "enum": [
                  "complete",
                  "truncated"
                ]
              },
              "retention_policies": {
                "type": "string",
                "enum": [
                  "complete",
                  "truncated"
                ]
              }
            }
          }
        }
      },
      "ApmPolicyUpdate": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "expected_authority_epoch"
        ],
        "minProperties": 2,
        "properties": {
          "expected_authority_epoch": {
            "type": "integer",
            "minimum": 1
          },
          "capture_enabled": {
            "type": "boolean",
            "const": false,
            "description": "`true` is unavailable while capture rollout is OFF."
          },
          "allowed_signals": {
            "type": "array",
            "maxItems": 2,
            "uniqueItems": true,
            "items": {
              "type": "string",
              "enum": [
                "traces",
                "rum_events"
              ]
            }
          },
          "sampling_policy_id": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/ApmScopedId"
              },
              {
                "type": "null"
              }
            ]
          },
          "retention_policy_version": {
            "type": "integer",
            "minimum": 1
          },
          "privacy_policy_version": {
            "type": "integer",
            "minimum": 1
          },
          "region_id": {
            "$ref": "#/components/schemas/ApmScopedId"
          },
          "data_plane_id": {
            "$ref": "#/components/schemas/ApmScopedId"
          }
        }
      },
      "ApmPolicyUpdateResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "ok",
          "project_id",
          "environment_id",
          "policy",
          "count",
          "truncated",
          "freshness",
          "completeness"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "const": true
          },
          "project_id": {
            "$ref": "#/components/schemas/ApmScopedId"
          },
          "environment_id": {
            "$ref": "#/components/schemas/ApmScopedId"
          },
          "policy": {
            "$ref": "#/components/schemas/ApmEnvironmentPolicy"
          },
          "count": {
            "type": "integer",
            "const": 1
          },
          "truncated": {
            "type": "boolean",
            "const": false
          },
          "freshness": {
            "$ref": "#/components/schemas/ApmAuthorityFreshness"
          },
          "completeness": {
            "type": "string",
            "const": "complete"
          }
        }
      },
      "ApmFreshness": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "watermark",
          "ingested_at"
        ],
        "properties": {
          "watermark": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "ingested_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "ApmTraceSummary": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "traceId",
          "completeness"
        ],
        "properties": {
          "traceId": {
            "type": "string",
            "pattern": "^(?!0{32}$)[0-9a-f]{32}$"
          },
          "rootSpanName": {
            "type": [
              "string",
              "null"
            ]
          },
          "rootServiceName": {
            "type": [
              "string",
              "null"
            ]
          },
          "startTime": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "endTime": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "durationMs": {
            "type": [
              "number",
              "null"
            ]
          },
          "spanCount": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0
          },
          "errorCount": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0
          },
          "status": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "ok",
              "error",
              null
            ]
          },
          "releaseId": {
            "type": [
              "string",
              "null"
            ]
          },
          "buildId": {
            "type": [
              "string",
              "null"
            ]
          },
          "samplingClass": {
            "type": [
              "string",
              "null"
            ]
          },
          "headSamplingDecision": {
            "type": [
              "string",
              "null"
            ]
          },
          "tailSamplingDecision": {
            "type": [
              "string",
              "null"
            ]
          },
          "samplingReason": {
            "type": [
              "string",
              "null"
            ]
          },
          "retentionDecision": {
            "type": [
              "string",
              "null"
            ]
          },
          "headState": {
            "type": [
              "string",
              "null"
            ]
          },
          "tailState": {
            "type": [
              "string",
              "null"
            ]
          },
          "partial": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "late": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "completeness": {
            "type": [
              "string",
              "null"
            ]
          },
          "samplingPolicyId": {
            "type": [
              "string",
              "null"
            ]
          },
          "retentionPolicyVersion": {
            "type": [
              "integer",
              "null"
            ]
          },
          "freshnessWatermark": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "ingestedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "schemaVersion": {
            "type": [
              "integer",
              "null"
            ]
          }
        }
      },
      "ApmTraceSpan": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "traceId",
          "spanId",
          "completeness"
        ],
        "properties": {
          "traceId": {
            "type": "string",
            "pattern": "^(?!0{32}$)[0-9a-f]{32}$"
          },
          "spanId": {
            "type": "string",
            "pattern": "^(?!0{16}$)[0-9a-f]{16}$"
          },
          "parentSpanId": {
            "type": [
              "string",
              "null"
            ]
          },
          "spanName": {
            "type": [
              "string",
              "null"
            ]
          },
          "serviceName": {
            "type": [
              "string",
              "null"
            ]
          },
          "spanKind": {
            "type": [
              "string",
              "null"
            ]
          },
          "startTime": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "endTime": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "durationMs": {
            "type": [
              "number",
              "null"
            ]
          },
          "statusCode": {
            "type": [
              "string",
              "null"
            ]
          },
          "statusMessage": {
            "type": [
              "string",
              "null"
            ]
          },
          "releaseId": {
            "type": [
              "string",
              "null"
            ]
          },
          "buildId": {
            "type": [
              "string",
              "null"
            ]
          },
          "claimedRumLinkId": {
            "type": [
              "string",
              "null"
            ]
          },
          "confirmedRumLinkId": {
            "type": [
              "string",
              "null"
            ]
          },
          "correlationState": {
            "type": "string",
            "enum": [
              "confirmed",
              "claimed",
              "unavailable"
            ]
          },
          "completeness": {
            "type": [
              "string",
              "null"
            ]
          },
          "eventTime": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "ingestedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "ApmTraceSearchResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "ok",
          "available",
          "project_id",
          "environment_id",
          "items",
          "count",
          "truncated",
          "next_cursor",
          "partial",
          "completeness",
          "freshness"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "const": true
          },
          "available": {
            "type": "boolean",
            "const": true
          },
          "project_id": {
            "$ref": "#/components/schemas/ApmScopedId"
          },
          "environment_id": {
            "$ref": "#/components/schemas/ApmScopedId"
          },
          "items": {
            "type": "array",
            "maxItems": 200,
            "items": {
              "$ref": "#/components/schemas/ApmTraceSummary"
            }
          },
          "count": {
            "type": "integer",
            "minimum": 0,
            "maximum": 200
          },
          "truncated": {
            "type": "boolean"
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ]
          },
          "partial": {
            "type": "boolean"
          },
          "completeness": {
            "type": "string"
          },
          "freshness": {
            "$ref": "#/components/schemas/ApmFreshness"
          }
        }
      },
      "ApmTraceDetailResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "ok",
          "available",
          "project_id",
          "environment_id",
          "summary",
          "timeline",
          "count",
          "truncated",
          "partial",
          "completeness",
          "freshness",
          "parent_edges_complete"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "const": true
          },
          "available": {
            "type": "boolean",
            "const": true
          },
          "project_id": {
            "$ref": "#/components/schemas/ApmScopedId"
          },
          "environment_id": {
            "$ref": "#/components/schemas/ApmScopedId"
          },
          "summary": {
            "$ref": "#/components/schemas/ApmTraceSummary"
          },
          "timeline": {
            "type": "array",
            "maxItems": 200,
            "items": {
              "$ref": "#/components/schemas/ApmTraceSpan"
            }
          },
          "count": {
            "type": "integer",
            "minimum": 0,
            "maximum": 200
          },
          "truncated": {
            "type": "boolean"
          },
          "partial": {
            "type": "boolean"
          },
          "completeness": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "summary",
              "timeline"
            ],
            "properties": {
              "summary": {
                "type": "string"
              },
              "timeline": {
                "type": "string"
              }
            }
          },
          "freshness": {
            "$ref": "#/components/schemas/ApmFreshness"
          },
          "parent_edges_complete": {
            "type": "boolean",
            "const": false
          }
        }
      },
      "ApmServiceHealth": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "service_name",
          "trace_count",
          "error_trace_count",
          "error_rate",
          "p50_duration_ms",
          "p95_duration_ms",
          "completeness",
          "freshness_watermark"
        ],
        "properties": {
          "service_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "trace_count": {
            "type": [
              "number",
              "null"
            ]
          },
          "error_trace_count": {
            "type": [
              "number",
              "null"
            ]
          },
          "error_rate": {
            "type": [
              "number",
              "null"
            ]
          },
          "p50_duration_ms": {
            "type": [
              "number",
              "null"
            ]
          },
          "p95_duration_ms": {
            "type": [
              "number",
              "null"
            ]
          },
          "completeness": {
            "type": "string",
            "enum": [
              "partial",
              "unknown"
            ]
          },
          "freshness_watermark": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "ApmDependencyHealth": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "source_service",
          "target_service",
          "protocol",
          "request_count",
          "error_count",
          "p50_duration_ms",
          "p95_duration_ms",
          "p99_duration_ms",
          "freshness_watermark"
        ],
        "properties": {
          "source_service": {
            "type": [
              "string",
              "null"
            ]
          },
          "target_service": {
            "type": [
              "string",
              "null"
            ]
          },
          "protocol": {
            "type": [
              "string",
              "null"
            ]
          },
          "request_count": {
            "type": [
              "number",
              "null"
            ]
          },
          "error_count": {
            "type": [
              "number",
              "null"
            ]
          },
          "p50_duration_ms": {
            "type": [
              "number",
              "null"
            ]
          },
          "p95_duration_ms": {
            "type": [
              "number",
              "null"
            ]
          },
          "p99_duration_ms": {
            "type": [
              "number",
              "null"
            ]
          },
          "freshness_watermark": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "ApmReleaseHealth": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "release_id",
          "build_id",
          "trace_count",
          "error_trace_count",
          "error_rate",
          "p50_duration_ms",
          "p95_duration_ms",
          "completeness",
          "freshness_watermark"
        ],
        "properties": {
          "release_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "build_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "trace_count": {
            "type": [
              "number",
              "null"
            ]
          },
          "error_trace_count": {
            "type": [
              "number",
              "null"
            ]
          },
          "error_rate": {
            "type": [
              "number",
              "null"
            ]
          },
          "p50_duration_ms": {
            "type": [
              "number",
              "null"
            ]
          },
          "p95_duration_ms": {
            "type": [
              "number",
              "null"
            ]
          },
          "completeness": {
            "type": "string",
            "enum": [
              "partial",
              "unknown"
            ]
          },
          "freshness_watermark": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "ApmServiceListResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "ok",
          "available",
          "project_id",
          "environment_id",
          "items",
          "count",
          "truncated",
          "partial",
          "completeness",
          "freshness_watermark"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "const": true
          },
          "available": {
            "type": "boolean",
            "const": true
          },
          "project_id": {
            "$ref": "#/components/schemas/ApmScopedId"
          },
          "environment_id": {
            "$ref": "#/components/schemas/ApmScopedId"
          },
          "items": {
            "type": "array",
            "maxItems": 200,
            "items": {
              "$ref": "#/components/schemas/ApmServiceHealth"
            }
          },
          "count": {
            "type": "integer",
            "minimum": 0,
            "maximum": 200
          },
          "truncated": {
            "type": "boolean"
          },
          "partial": {
            "type": "boolean"
          },
          "completeness": {
            "type": "string",
            "enum": [
              "partial",
              "unknown"
            ]
          },
          "freshness_watermark": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "ApmServiceHealthResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "ok",
          "available",
          "partial",
          "reason",
          "project_id",
          "environment_id",
          "service_name",
          "health",
          "health_available",
          "items",
          "count",
          "dependencies_available",
          "truncated",
          "completeness",
          "freshness_watermark"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "const": true
          },
          "available": {
            "type": "boolean",
            "const": true
          },
          "partial": {
            "type": "boolean"
          },
          "reason": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "partial_warehouse_unavailable",
              "source_incomplete",
              null
            ]
          },
          "project_id": {
            "$ref": "#/components/schemas/ApmScopedId"
          },
          "environment_id": {
            "$ref": "#/components/schemas/ApmScopedId"
          },
          "service_name": {
            "type": "string"
          },
          "health": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/ApmServiceHealth"
              },
              {
                "type": "null"
              }
            ]
          },
          "health_available": {
            "type": "boolean"
          },
          "items": {
            "type": "array",
            "maxItems": 200,
            "items": {
              "$ref": "#/components/schemas/ApmDependencyHealth"
            }
          },
          "count": {
            "type": "integer",
            "minimum": 0,
            "maximum": 200
          },
          "dependencies_available": {
            "type": "boolean"
          },
          "truncated": {
            "type": "boolean"
          },
          "completeness": {
            "type": "string",
            "enum": [
              "partial",
              "unknown"
            ]
          },
          "freshness_watermark": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "ApmReleaseHealthResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "ok",
          "available",
          "project_id",
          "environment_id",
          "release_id",
          "items",
          "count",
          "truncated",
          "partial",
          "completeness",
          "freshness_watermark"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "const": true
          },
          "available": {
            "type": "boolean",
            "const": true
          },
          "project_id": {
            "$ref": "#/components/schemas/ApmScopedId"
          },
          "environment_id": {
            "$ref": "#/components/schemas/ApmScopedId"
          },
          "release_id": {
            "$ref": "#/components/schemas/ApmScopedId"
          },
          "items": {
            "type": "array",
            "maxItems": 200,
            "items": {
              "$ref": "#/components/schemas/ApmReleaseHealth"
            }
          },
          "count": {
            "type": "integer",
            "minimum": 0,
            "maximum": 200
          },
          "truncated": {
            "type": "boolean"
          },
          "partial": {
            "type": "boolean"
          },
          "completeness": {
            "type": "string",
            "enum": [
              "partial",
              "unknown"
            ]
          },
          "freshness_watermark": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "ApmExportCreate": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "project_id",
          "environment_id",
          "from",
          "to",
          "fact_names",
          "purpose"
        ],
        "properties": {
          "project_id": {
            "$ref": "#/components/schemas/ApmScopedId"
          },
          "environment_id": {
            "$ref": "#/components/schemas/ApmScopedId"
          },
          "from": {
            "type": "string",
            "format": "date-time",
            "description": "Range start; interval must not exceed 31 days."
          },
          "to": {
            "type": "string",
            "format": "date-time",
            "description": "Range end after `from`; interval must not exceed 31 days."
          },
          "fact_names": {
            "type": "array",
            "minItems": 1,
            "maxItems": 10,
            "uniqueItems": true,
            "items": {
              "type": "string",
              "enum": [
                "apm_spans",
                "apm_trace_summaries",
                "rum_events",
                "rum_vital_facts",
                "rum_session_summaries",
                "apm_metric_points",
                "apm_log_records",
                "apm_service_edge_facts",
                "apm_error_occurrences",
                "apm_error_group_facts"
              ]
            }
          },
          "purpose": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128,
            "pattern": "^[A-Za-z0-9][A-Za-z0-9 ._:/-]{0,127}$"
          },
          "expires_in_seconds": {
            "type": "integer",
            "minimum": 60,
            "maximum": 604800,
            "default": 3600
          }
        }
      },
      "ApmExportStatus": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "ok",
          "project_id",
          "environment_id",
          "export_manifest_id",
          "purpose",
          "fact_names",
          "state",
          "row_count",
          "byte_count",
          "created_at",
          "expires_at",
          "completed_at"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "const": true
          },
          "project_id": {
            "$ref": "#/components/schemas/ApmScopedId"
          },
          "environment_id": {
            "$ref": "#/components/schemas/ApmScopedId"
          },
          "export_manifest_id": {
            "$ref": "#/components/schemas/ApmScopedId"
          },
          "purpose": {
            "type": "string"
          },
          "fact_names": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "state": {
            "type": "string",
            "description": "Asynchronous manifest state reported by the runtime; consumers must tolerate future states."
          },
          "row_count": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0
          },
          "byte_count": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "completed_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "ApmDownloadGrantRequest": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "expires_in_seconds": {
            "type": "integer",
            "minimum": 1,
            "maximum": 300,
            "default": 60
          }
        }
      },
      "ApmPrivacyExportStatus": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "ok",
          "privacy_request_id",
          "project_id",
          "environment_id",
          "export_manifest_id",
          "purpose",
          "fact_names",
          "state",
          "row_count",
          "byte_count",
          "created_at",
          "expires_at",
          "completed_at"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "const": true
          },
          "privacy_request_id": {
            "$ref": "#/components/schemas/ApmScopedId"
          },
          "project_id": {
            "$ref": "#/components/schemas/ApmScopedId"
          },
          "environment_id": {
            "$ref": "#/components/schemas/ApmScopedId"
          },
          "export_manifest_id": {
            "$ref": "#/components/schemas/ApmScopedId"
          },
          "purpose": {
            "type": "string"
          },
          "fact_names": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "state": {
            "type": "string",
            "description": "Asynchronous manifest state reported by the runtime; consumers must tolerate future states."
          },
          "row_count": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0
          },
          "byte_count": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "completed_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "ApmErasureStatus": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "ok",
          "privacy_request_id",
          "project_id",
          "environment_id",
          "state",
          "attempts",
          "created_at",
          "updated_at",
          "completed_at",
          "stores",
          "deleted"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "const": true
          },
          "privacy_request_id": {
            "$ref": "#/components/schemas/ApmScopedId"
          },
          "project_id": {
            "$ref": "#/components/schemas/ApmScopedId"
          },
          "environment_id": {
            "$ref": "#/components/schemas/ApmScopedId"
          },
          "state": {
            "type": "string"
          },
          "attempts": {
            "type": "integer",
            "minimum": 0
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "completed_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "stores": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "count",
              "pending",
              "running",
              "succeeded",
              "failed"
            ],
            "properties": {
              "count": {
                "type": "integer",
                "minimum": 0
              },
              "pending": {
                "type": "integer",
                "minimum": 0
              },
              "running": {
                "type": "integer",
                "minimum": 0
              },
              "succeeded": {
                "type": "integer",
                "minimum": 0
              },
              "failed": {
                "type": "integer",
                "minimum": 0
              }
            }
          },
          "deleted": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "rows",
              "objects",
              "bytes"
            ],
            "properties": {
              "rows": {
                "type": "integer",
                "minimum": 0
              },
              "objects": {
                "type": "integer",
                "minimum": 0
              },
              "bytes": {
                "type": "integer",
                "minimum": 0
              }
            }
          }
        }
      },
      "OtlpAnyValue": {
        "type": "object",
        "description": "Proto3-JSON mapping of `opentelemetry.proto.common.v1.AnyValue` — exactly one property is present per the proto3 JSON oneof convention.",
        "properties": {
          "stringValue": {
            "type": "string"
          },
          "boolValue": {
            "type": "boolean"
          },
          "intValue": {
            "type": [
              "string",
              "integer"
            ],
            "description": "Proto3-JSON int64 mapping; a decimal string once the value exceeds Number.isSafeInteger range."
          },
          "doubleValue": {
            "type": "number"
          },
          "arrayValue": {
            "type": "object",
            "properties": {
              "values": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/OtlpAnyValue"
                }
              }
            }
          },
          "kvlistValue": {
            "type": "object",
            "properties": {
              "values": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/OtlpKeyValue"
                }
              }
            }
          },
          "bytesValue": {
            "type": "string",
            "format": "byte",
            "description": "Base64-encoded (proto3-JSON `bytes` mapping)."
          }
        }
      },
      "OtlpKeyValue": {
        "type": "object",
        "properties": {
          "key": {
            "type": "string"
          },
          "value": {
            "$ref": "#/components/schemas/OtlpAnyValue"
          }
        }
      },
      "OtlpSpanEvent": {
        "type": "object",
        "properties": {
          "timeUnixNano": {
            "type": "string",
            "description": "Proto3-JSON int64 mapping (nanoseconds since the Unix epoch), encoded as a decimal string."
          },
          "name": {
            "type": "string"
          },
          "attributes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OtlpKeyValue"
            }
          },
          "droppedAttributesCount": {
            "type": "integer",
            "minimum": 0
          }
        }
      },
      "OtlpSpanLink": {
        "type": "object",
        "properties": {
          "traceId": {
            "type": "string",
            "format": "byte",
            "description": "Base64-encoded 16-byte trace id (proto3-JSON `bytes` mapping)."
          },
          "spanId": {
            "type": "string",
            "format": "byte",
            "description": "Base64-encoded 8-byte span id (proto3-JSON `bytes` mapping)."
          },
          "traceState": {
            "type": "string"
          },
          "attributes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OtlpKeyValue"
            }
          },
          "droppedAttributesCount": {
            "type": "integer",
            "minimum": 0
          },
          "flags": {
            "type": "integer",
            "minimum": 0
          }
        }
      },
      "OtlpSpan": {
        "type": "object",
        "description": "A single decoded span may still be dropped during post-decode validation — see `partialSuccess` on `OtlpTraceIngestResult` — so no property is `required` here; the wire format itself never rejects a well-formed but incomplete span.",
        "properties": {
          "traceId": {
            "type": "string",
            "format": "byte",
            "description": "Base64-encoded 16-byte trace id."
          },
          "spanId": {
            "type": "string",
            "format": "byte",
            "description": "Base64-encoded 8-byte span id."
          },
          "traceState": {
            "type": "string"
          },
          "parentSpanId": {
            "type": "string",
            "format": "byte",
            "description": "Base64-encoded 8-byte parent span id; absent for a root span."
          },
          "flags": {
            "type": "integer",
            "minimum": 0
          },
          "name": {
            "type": "string"
          },
          "kind": {
            "type": [
              "string",
              "integer"
            ],
            "description": "Proto3-JSON enum mapping — the OTLP SpanKind name (e.g. SPAN_KIND_SERVER) or its raw numeric value."
          },
          "startTimeUnixNano": {
            "type": "string"
          },
          "endTimeUnixNano": {
            "type": "string"
          },
          "attributes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OtlpKeyValue"
            }
          },
          "droppedAttributesCount": {
            "type": "integer",
            "minimum": 0
          },
          "events": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OtlpSpanEvent"
            }
          },
          "droppedEventsCount": {
            "type": "integer",
            "minimum": 0
          },
          "links": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OtlpSpanLink"
            }
          },
          "droppedLinksCount": {
            "type": "integer",
            "minimum": 0
          },
          "status": {
            "type": "object",
            "properties": {
              "message": {
                "type": "string"
              },
              "code": {
                "type": [
                  "string",
                  "integer"
                ],
                "description": "Proto3-JSON enum mapping — STATUS_CODE_UNSET / STATUS_CODE_OK / STATUS_CODE_ERROR, or its raw numeric value."
              }
            }
          }
        }
      },
      "OtlpScopeSpans": {
        "type": "object",
        "properties": {
          "scope": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string"
              },
              "version": {
                "type": "string"
              },
              "attributes": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/OtlpKeyValue"
                }
              },
              "droppedAttributesCount": {
                "type": "integer",
                "minimum": 0
              }
            }
          },
          "spans": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OtlpSpan"
            }
          },
          "schemaUrl": {
            "type": "string"
          }
        }
      },
      "OtlpResourceSpans": {
        "type": "object",
        "properties": {
          "resource": {
            "type": "object",
            "properties": {
              "attributes": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/OtlpKeyValue"
                }
              },
              "droppedAttributesCount": {
                "type": "integer",
                "minimum": 0
              }
            }
          },
          "scopeSpans": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OtlpScopeSpans"
            }
          },
          "schemaUrl": {
            "type": "string"
          }
        }
      },
      "OtlpExportTraceServiceRequest": {
        "type": "object",
        "description": "Proto3-JSON mapping of OTLP's `opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest` — the exact JSON shape an OpenTelemetry SDK or Collector's OTLP/HTTP JSON exporter already sends. The 500-span cap (`POST /v1/traces`'s 413 `apm_batch_too_large`) is counted across every `resourceSpans[].scopeSpans[].spans[]` in the whole request and is therefore not expressible as a single array's `maxItems`.",
        "properties": {
          "resourceSpans": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OtlpResourceSpans"
            }
          }
        }
      },
      "OtlpTraceIngestResult": {
        "type": "object",
        "additionalProperties": false,
        "description": "Proto3-JSON mapping of OTLP's `ExportTraceServiceResponse`. An empty object means every span was accepted; `partialSuccess` is present only when one or more spans failed validation and were dropped — the whole request is never rejected once past authentication, decoding, and the batch-size cap.",
        "properties": {
          "partialSuccess": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "rejectedSpans"
            ],
            "properties": {
              "rejectedSpans": {
                "type": "string",
                "description": "Decimal count of rejected spans, encoded as a string (proto3-JSON int64 mapping)."
              },
              "errorMessage": {
                "type": "string"
              }
            }
          }
        }
      },
      "OtlpErrorDetail": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "@type",
          "reason",
          "domain",
          "metadata"
        ],
        "properties": {
          "@type": {
            "type": "string",
            "const": "type.googleapis.com/google.rpc.ErrorInfo"
          },
          "reason": {
            "type": "string",
            "enum": [
              "apm_auth_missing",
              "apm_auth_invalid",
              "apm_auth_expired",
              "apm_scope_denied",
              "apm_purpose_disabled",
              "apm_authority_unavailable",
              "apm_rate_limited",
              "apm_unsupported_media_type",
              "apm_body_too_large",
              "apm_malformed_otlp_json",
              "apm_malformed_otlp_protobuf",
              "apm_malformed_metrics_payload",
              "apm_malformed_logs_payload",
              "apm_malformed_profile_json",
              "apm_profile_storage_unavailable",
              "apm_batch_too_large",
              "apm_queue_unavailable"
            ],
            "description": "Union of every reason code any of the four OTLP-flavoured ingest routes (`POST /v1/traces`, `/v1/metrics`, `/v1/logs`, `/v1/profiles`) can return — not every operation returns every value (e.g. only `/v1/profiles` returns `apm_profile_storage_unavailable`; only `/v1/traces` returns `apm_malformed_otlp_json`/`apm_malformed_otlp_protobuf`)."
          },
          "domain": {
            "type": "string",
            "const": "ingest.noxtica.com"
          },
          "metadata": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "requestId",
              "retryable"
            ],
            "properties": {
              "requestId": {
                "type": "string"
              },
              "retryable": {
                "type": "string",
                "enum": [
                  "true",
                  "false"
                ]
              }
            }
          }
        }
      },
      "OtlpStatus": {
        "type": "object",
        "required": [
          "code",
          "message"
        ],
        "description": "The error body of the OTLP ingestion operations (`POST /v1/traces`, `/v1/metrics`, `/v1/logs` and `/v1/profiles`), distinct from the `{error, requestId}` envelope of every other operation. Two shapes exist and either can be returned: the collector hosts answer a `google.rpc.Status`-shaped body (`code` is the gRPC status code and `details[0].reason` the reason), and the dedicated ingest hosts answer `{code, message, error}` (`code` is the HTTP status and `error` the reason). The reason strings are the same. Branch on the HTTP status and the reason, never on `code`. `POST /v1/deployments` uses its own envelope (`ApmDeploymentError`).",
        "properties": {
          "code": {
            "type": "integer",
            "description": "On the collector hosts the gRPC status code mapped from the HTTP status (400->3 INVALID_ARGUMENT, 401->16 UNAUTHENTICATED, 403->7 PERMISSION_DENIED, 413->8 RESOURCE_EXHAUSTED, 415->3 INVALID_ARGUMENT, 429->8 RESOURCE_EXHAUSTED, 502 and 503->14 UNAVAILABLE); on the ingest hosts the HTTP status itself."
          },
          "message": {
            "type": "string"
          },
          "error": {
            "type": "string",
            "description": "The reason string on the ingest hosts (the same value as `details[0].reason` on the collector hosts)."
          },
          "details": {
            "type": "array",
            "minItems": 1,
            "maxItems": 1,
            "items": {
              "$ref": "#/components/schemas/OtlpErrorDetail"
            },
            "description": "Present on the collector hosts only."
          }
        }
      },
      "OtlpExportMetricsServiceRequest": {
        "type": "object",
        "description": "Proto3-JSON mapping of OTLP's `opentelemetry.proto.collector.metrics.v1.ExportMetricsServiceRequest`. Modeled at the top-level `resourceMetrics` shape only, per this spec's OTLP-payload convention (see `OtlpExportTraceServiceRequest`'s own note) — each metric's own `gauge`/`sum`/`histogram`/ `exponentialHistogram`/`summary` data-point union is real proto3-JSON the collector decodes but is not exhaustively re-typed here. The 500-data-point cap (`POST /v1/metrics`'s 413 `apm_batch_too_large`) is counted across every data-point array in the whole request and is therefore not expressible as a single array's `maxItems`.",
        "properties": {
          "resourceMetrics": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true,
              "description": "One proto3-JSON `ResourceMetrics` entry (`resource`, `scopeMetrics[]`, `schemaUrl`) — see the OTLP metrics proto3-JSON schema for the full nested shape."
            }
          }
        }
      },
      "OtlpMetricsIngestResult": {
        "type": "object",
        "additionalProperties": false,
        "description": "Proto3-JSON mapping of OTLP's `ExportMetricsServiceResponse`. An empty object means every data point was accepted; `partialSuccess` is present only when one or more data points failed validation and were dropped — the whole request is never rejected once past authentication, decoding, and the batch-size cap.",
        "properties": {
          "partialSuccess": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "rejectedDataPoints"
            ],
            "properties": {
              "rejectedDataPoints": {
                "type": "string",
                "description": "Decimal count of rejected data points, encoded as a string (proto3-JSON int64 mapping)."
              },
              "errorMessage": {
                "type": "string"
              }
            }
          }
        }
      },
      "OtlpExportLogsServiceRequest": {
        "type": "object",
        "description": "Proto3-JSON mapping of OTLP's `opentelemetry.proto.collector.logs.v1.ExportLogsServiceRequest`. Modeled at the top-level `resourceLogs` shape only, per this spec's OTLP-payload convention (see `OtlpExportTraceServiceRequest`'s own note). The 500-log-record cap (`POST /v1/logs`'s 413 `apm_batch_too_large`) is counted across every `resourceLogs[].scopeLogs[].logRecords[]` in the whole request and is therefore not expressible as a single array's `maxItems`.",
        "properties": {
          "resourceLogs": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true,
              "description": "One proto3-JSON `ResourceLogs` entry (`resource`, `scopeLogs[]`, `schemaUrl`) — see the OTLP logs proto3-JSON schema for the full nested shape."
            }
          }
        }
      },
      "OtlpLogsIngestResult": {
        "type": "object",
        "additionalProperties": false,
        "description": "Proto3-JSON mapping of OTLP's `ExportLogsServiceResponse`. An empty object means every log record was accepted; `partialSuccess` is present only when one or more log records failed validation and were dropped — the whole request is never rejected once past authentication, decoding, and the batch-size cap.",
        "properties": {
          "partialSuccess": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "rejectedLogRecords"
            ],
            "properties": {
              "rejectedLogRecords": {
                "type": "string",
                "description": "Decimal count of rejected log records, encoded as a string (proto3-JSON int64 mapping)."
              },
              "errorMessage": {
                "type": "string"
              }
            }
          }
        }
      },
      "OtlpProfilesData": {
        "type": "object",
        "description": "Proto3-JSON mapping of OTLP profiling's `ProfilesData` container (`opentelemetry.proto.profiles.v1development.ProfilesData`) — profiling is still an OTel \"development\" signal, hence the bare data-container shape rather than an `ExportXServiceRequest` envelope like traces/metrics/logs use. Modeled at the top-level `resourceProfiles` shape only, per this spec's OTLP-payload convention (see `OtlpExportTraceServiceRequest`'s own note). The 20-profile cap (`POST /v1/profiles`'s 413 `apm_batch_too_large`) is counted across every `resourceProfiles[].scopeProfiles[].profiles[]` in the whole request and is therefore not expressible as a single array's `maxItems`.",
        "properties": {
          "resourceProfiles": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true,
              "description": "One proto3-JSON `ResourceProfiles` entry (`resource`, `scopeProfiles[]`) — see the OTLP profiles proto3-JSON schema for the full nested shape."
            }
          }
        }
      },
      "OtlpProfilesIngestResult": {
        "type": "object",
        "additionalProperties": false,
        "description": "An empty object means every profile was accepted and persisted; `partialSuccess` is present only when one or more profiles failed validation, or were stored with an unrecognized `profileType`, without failing the whole request.",
        "properties": {
          "partialSuccess": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "rejectedProfiles"
            ],
            "properties": {
              "rejectedProfiles": {
                "type": "string",
                "description": "Decimal count of rejected profiles, encoded as a string."
              },
              "errorMessage": {
                "type": "string"
              }
            }
          }
        }
      },
      "ApmDeploymentMarkerRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "service",
          "version",
          "environment"
        ],
        "description": "`POST /v1/deployments`'s own single-row REST body — never an OTLP batch.",
        "properties": {
          "service": {
            "type": "string",
            "pattern": "^[A-Za-z0-9._:/-]{1,128}$"
          },
          "version": {
            "type": "string",
            "pattern": "^[A-Za-z0-9_.:/-]{1,128}$",
            "description": "Also becomes the canonical spine's `release_id` — `release_id` equals the request `version`, byte-for-byte."
          },
          "environment": {
            "type": "string",
            "pattern": "^[A-Za-z0-9._:-]{1,256}$",
            "description": "MUST equal the authenticated credential's own `environmentId` scope — a mismatch is rejected with 403 `apm_environment_mismatch` rather than redirecting the marker."
          },
          "commit": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^[0-9a-f]{7,64}$",
            "description": "Git commit SHA, 7-64 lowercase hex characters. Omit or send `null` if not applicable."
          },
          "timestamp": {
            "type": "string",
            "format": "date-time",
            "description": "Defaults to the server's receipt time if omitted. MUST be less than or equal to the receipt time — a deployment marker can never be timestamped in the future."
          }
        }
      },
      "ApmDeploymentMarkerAccepted": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "ok",
          "deployment_id",
          "service",
          "version",
          "environment",
          "commit",
          "timestamp"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "const": true
          },
          "deployment_id": {
            "type": "string",
            "description": "Server-generated `dep_<uuid>` identifier."
          },
          "service": {
            "type": "string"
          },
          "version": {
            "type": "string"
          },
          "environment": {
            "type": "string"
          },
          "commit": {
            "type": [
              "string",
              "null"
            ]
          },
          "timestamp": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ApmDeploymentError": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "ok",
          "error",
          "message",
          "requestId"
        ],
        "description": "`POST /v1/deployments`'s own plain-JSON error envelope — distinct from the `google.rpc.Status`-shaped `OtlpStatus` the other three OTLP ingest routes plus `/v1/traces` share.",
        "properties": {
          "ok": {
            "type": "boolean",
            "const": false
          },
          "error": {
            "type": "string",
            "enum": [
              "apm_auth_missing",
              "apm_auth_invalid",
              "apm_auth_expired",
              "apm_scope_denied",
              "apm_purpose_disabled",
              "apm_authority_unavailable",
              "apm_rate_limited",
              "apm_unsupported_media_type",
              "apm_body_too_large",
              "apm_malformed_json",
              "apm_invalid_payload",
              "apm_environment_mismatch",
              "apm_queue_unavailable"
            ]
          },
          "message": {
            "type": "string"
          },
          "requestId": {
            "type": "string"
          }
        }
      },
      "v1_ErrorEnvelope": {
        "type": "object",
        "required": [
          "error",
          "requestId"
        ],
        "properties": {
          "error": {
            "type": "string",
            "description": "Machine-readable error string; route-specific values are listed on each operation."
          },
          "requestId": {
            "type": "string",
            "description": "Correlation id for this call; quote it when you contact support."
          }
        }
      },
      "InvalidApiKeyError": {
        "type": "object",
        "required": [
          "error",
          "requestId"
        ],
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "invalid_api_key",
              "server_misconfigured"
            ]
          },
          "message": {
            "type": "string"
          },
          "requestId": {
            "type": "string"
          }
        }
      },
      "ScopeForbiddenError": {
        "type": "object",
        "required": [
          "error",
          "requestId"
        ],
        "properties": {
          "error": {
            "type": "string",
            "description": "Always \"API key does not have <scope> scope\", naming the missing scope."
          },
          "requestId": {
            "type": "string"
          }
        }
      },
      "NotFoundError": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "Not found"
            ]
          }
        }
      },
      "HealthStatus": {
        "type": "object",
        "required": [
          "status",
          "version",
          "timestamp"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "ok",
              "degraded"
            ]
          },
          "version": {
            "type": "string",
            "description": "The deployed collector version, or `unknown`."
          },
          "timestamp": {
            "type": "string",
            "format": "date-time",
            "description": "Server time of the response."
          }
        }
      },
      "Jwks": {
        "type": "object",
        "required": [
          "keys"
        ],
        "properties": {
          "keys": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "kty",
                "crv",
                "x",
                "y",
                "kid",
                "use",
                "alg"
              ],
              "properties": {
                "kty": {
                  "type": "string",
                  "enum": [
                    "EC"
                  ]
                },
                "crv": {
                  "type": "string",
                  "enum": [
                    "P-256"
                  ]
                },
                "x": {
                  "type": "string",
                  "description": "base64url X coordinate."
                },
                "y": {
                  "type": "string",
                  "description": "base64url Y coordinate."
                },
                "kid": {
                  "type": "string",
                  "description": "Key id; matches the `kid` of the envelopes signed with it."
                },
                "use": {
                  "type": "string",
                  "enum": [
                    "sig"
                  ]
                },
                "alg": {
                  "type": "string",
                  "enum": [
                    "ES256"
                  ]
                }
              }
            }
          }
        }
      },
      "CodingAgentError": {
        "type": "object",
        "required": [
          "code",
          "message",
          "error"
        ],
        "properties": {
          "code": {
            "type": "integer",
            "description": "The HTTP status code."
          },
          "message": {
            "type": "string"
          },
          "error": {
            "type": "string",
            "description": "Machine-readable reason; branch on it, not on `message`."
          }
        }
      },
      "CodingAgentSignal": {
        "type": "object",
        "required": [
          "signal",
          "reference_id",
          "excerpt",
          "observed_at"
        ],
        "properties": {
          "signal": {
            "type": "string",
            "description": "The key scope the row came from, for example `rum_errors` or `apm_traces`."
          },
          "reference_id": {
            "type": "string",
            "description": "The id of the source record (event, trace, error group, metric series)."
          },
          "excerpt": {
            "type": "string",
            "description": "A short human-readable summary of the record."
          },
          "observed_at": {
            "type": "string",
            "format": "date-time"
          },
          "metric_value": {
            "type": "number",
            "description": "Present when the record carries a numeric value."
          }
        }
      },
      "CodingAgentSpan": {
        "type": "object",
        "required": [
          "span_id",
          "service_name",
          "operation_name",
          "start_time",
          "end_time",
          "duration_ns",
          "status_code"
        ],
        "properties": {
          "span_id": {
            "type": "string"
          },
          "parent_span_id": {
            "type": "string"
          },
          "service_name": {
            "type": "string"
          },
          "operation_name": {
            "type": "string"
          },
          "start_time": {
            "type": "string",
            "format": "date-time"
          },
          "end_time": {
            "type": "string",
            "format": "date-time"
          },
          "duration_ns": {
            "type": "integer",
            "format": "int64"
          },
          "status_code": {
            "type": "string"
          },
          "status_message": {
            "type": "string"
          }
        }
      },
      "CodingAgentTrace": {
        "type": "object",
        "required": [
          "trace_id",
          "spans"
        ],
        "properties": {
          "trace_id": {
            "type": "string"
          },
          "spans": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CodingAgentSpan"
            }
          }
        }
      },
      "CodingAgentErrorOccurrence": {
        "type": "object",
        "required": [
          "occurrence_id",
          "exception_type",
          "observed_at"
        ],
        "properties": {
          "occurrence_id": {
            "type": "string"
          },
          "exception_type": {
            "type": "string"
          },
          "exception_message": {
            "type": "string"
          },
          "observed_at": {
            "type": "string",
            "format": "date-time"
          },
          "release_id": {
            "type": "string"
          }
        }
      },
      "CodingAgentErrorGroup": {
        "type": "object",
        "required": [
          "error_group_id",
          "first_seen",
          "last_seen",
          "occurrence_count",
          "affected_release_ids",
          "occurrences"
        ],
        "properties": {
          "error_group_id": {
            "type": "string"
          },
          "first_seen": {
            "type": "string",
            "format": "date-time"
          },
          "last_seen": {
            "type": "string",
            "format": "date-time"
          },
          "occurrence_count": {
            "type": "integer",
            "format": "int64"
          },
          "affected_release_ids": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "occurrences": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CodingAgentErrorOccurrence"
            }
          }
        }
      },
      "VerdictWebhookData": {
        "type": "object",
        "description": "The verdict of one scored submission. Never carries a raw IP address or personal data.",
        "required": [
          "device_id",
          "domain_id",
          "event_id"
        ],
        "properties": {
          "score": {
            "type": "number",
            "description": "The numeric risk score."
          },
          "risk_level": {
            "type": "string",
            "description": "The verdict band, for example `low`, `medium`, `high` or `critical`."
          },
          "confidence": {
            "type": "number",
            "description": "Model confidence from 0 to 1."
          },
          "flags": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The risk flags that fired."
          },
          "reason_codes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The published reason-code projection of `flags`; empty unless reason-code output is enabled for your organisation."
          },
          "device_id": {
            "type": "string",
            "description": "The opaque device id. An empty string means that no stable per-device identity is available for this event."
          },
          "domain_id": {
            "type": "string",
            "description": "Your domain id."
          },
          "event_id": {
            "type": "string",
            "description": "The request id of the submission or attestation; always present."
          }
        }
      },
      "VerdictWebhookEvent": {
        "type": "object",
        "description": "The JSON body of a verdict webhook delivery.",
        "required": [
          "id",
          "type",
          "created_at",
          "tenant_id",
          "data"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "The delivery id; equals `X-Noxtica-Delivery`."
          },
          "type": {
            "type": "string",
            "enum": [
              "submission.scored",
              "risk.high",
              "risk.flagged",
              "risk.cluster_flagged"
            ]
          },
          "created_at": {
            "type": "integer",
            "format": "int64",
            "description": "Unix ms the event was produced."
          },
          "tenant_id": {
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/VerdictWebhookData"
          }
        }
      },
      "AgentLinkedWebhookData": {
        "type": "object",
        "description": "The first link between a verified agent and one of your accounts. Never carries a raw account id, IP address or personal data.",
        "required": [
          "account_hash",
          "agent_keyid",
          "agent_host",
          "device_id",
          "domain_id",
          "event_id"
        ],
        "properties": {
          "account_hash": {
            "type": "string",
            "description": "The keyed 16-character lowercase-hex account pseudonym."
          },
          "agent_keyid": {
            "type": "string",
            "description": "The verified agent's `Signature-Input` key id."
          },
          "agent_host": {
            "type": [
              "string",
              "null"
            ],
            "description": "The verified agent's directory host, or `null`."
          },
          "device_id": {
            "type": "string"
          },
          "domain_id": {
            "type": "string"
          },
          "event_id": {
            "type": "string"
          }
        }
      },
      "AgentLinkedWebhookEvent": {
        "type": "object",
        "description": "The JSON body of an `account.agent_linked` delivery.",
        "required": [
          "id",
          "type",
          "created_at",
          "tenant_id",
          "data"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "The delivery id; equals `X-Noxtica-Delivery`."
          },
          "type": {
            "type": "string",
            "enum": [
              "account.agent_linked"
            ]
          },
          "created_at": {
            "type": "integer",
            "format": "int64",
            "description": "Unix ms the event was produced."
          },
          "tenant_id": {
            "type": "string"
          },
          "data": {
            "$ref": "#/components/schemas/AgentLinkedWebhookData"
          }
        }
      }
    },
    "headers": {
      "RateLimitLimit": {
        "description": "The request limit of the token's bucket.",
        "schema": {
          "type": "integer"
        }
      },
      "RateLimitRemaining": {
        "description": "Requests left in the current window.",
        "schema": {
          "type": "integer"
        }
      },
      "RateLimitReset": {
        "description": "Unix time, in seconds, at which the window resets.",
        "schema": {
          "type": "integer"
        }
      },
      "RateLimitBucket": {
        "description": "The name of the rate-limit bucket (`mcp`).",
        "schema": {
          "type": "string"
        }
      },
      "NoStore": {
        "description": "APM control/query responses are never cacheable.",
        "schema": {
          "type": "string",
          "const": "no-store"
        }
      }
    }
  }
}
