# Get the threat overview (admin)

`GET /v1/admin/orgs/{slug}/threats`

Returns every signal of the threat catalog counted over the window: the
failed sign-ins, locks and throttles that show credentials being
guessed, the second-factor failures and locks, the grants and tokens
refused at the protocol endpoints, the clients that failed to prove who
they are, the registrations and names that look built to mislead, the
privileged calls refused, and the malformed traffic turned away at the
edge. Each signal carries its count, the count of the equal window
before, its counts per bucket, the status that judges them against the
signal's recommended threshold, the audit list filters that list exactly
the records it counted, and the frameworks that describe the threat.
The shape of the window's failed sign-ins is read apart, at
`/threats/sign-ins`, so the signals are served while it is counted.

Everything is an aggregate: no address, account or client is named. The
drill-down is the audit list, under its own permissions.

`bucket` is one of the audit counts' fixed list, each allowed up to a
window: `1m` up to 2 hours, `10m` up to 2 days, `1h` up to 31 days and
`1d` up to the 90-day maximum `x-window` declares. Omitted, it is the
finest the window allows, and the window is widened to whole buckets
and echoed. A window longer than the bucket asked for allows is refused
with `window_too_large`.

Answers are cached per organization, bucket and window for at least the
dashboard's shortest refresh interval, longer in proportion to the
window up to a few minutes, and replicas sharing a cache compute each
one once. An aggregate runs under a deadline and a per-server
concurrency cap; past either it is answered 503 `busy` with Retry-After
rather than queued.

Requires the `nauthera.threats:read` scope and the `threats.read`
permission. A caller is confined to its own org unless a platform role
held in the main org admits it to every org. Reading the overview is
recorded at the trace level only, so polling adds nothing to the audit
log at the levels a deployment usually runs.

## Authorization

- [Bearer token](https://www.nauthera.io/docs/v1/api#auth-bearerAuth) (`bearerAuth`) and [OAuth 2.0](https://www.nauthera.io/docs/v1/api#auth-oauth2) (`oauth2`) with scope `nauthera.threats:read`

Authorization header: The access token, as `Bearer <token>` (RFC 6750 §2.1) or, for a sender-constrained token, `DPoP <token>` (RFC 9449 §7.1). A token minted with a `cnf.jkt` confirmation is only accepted together with a `DPoP` proof signed by that key, whichever of the two schemes carries it.

Requires the permission [`threats.read`](https://www.nauthera.io/docs/v1/api#permission-threats.read): Read an organization's threat analytics: the attack signals counted from its audit log, against their recommended thresholds.

This endpoint is rate limited; it answers `429` when a limit is hit.

## Path parameters

- `slug` (string, required): The organization slug. It names the TENANT OF RECORD for the operation: the rows it reads and writes, the policy its secrets are derived under, and the organization its audit record is filed against all come from this organization. A token is admitted only through its own slug, except a main-org token, which may be admitted through any — so cross-tenant administration is performed through the TARGET tenant's slug, never by naming its resources through another. A token reaching for a slug it may not be admitted through is refused identically whether that organization exists or not. Constraints: 1–64 characters.

## Query parameters

- `bucket` (enum, optional): The bucket length. Omitted, the finest the window allows. One of: `"1m"`, `"10m"`, `"1h"`, `"1d"`.
- `from` (string (date-time), optional): Inclusive start of the window (RFC3339). Defaults to 30 days before `to`. The window from `from` to `to` may span at most 90 days.
- `to` (string (date-time), optional): Exclusive end of the window (RFC3339). Defaults to now. The window from `from` to `to` may span at most 90 days.

## Headers

- `DPoP` (string, optional): DPoP proof JWT (RFC 9449 §4). REQUIRED on a request presenting a DPoP-bound access token, and it must be signed by the key named in the token's `cnf.jkt` and cover this request's method and URI. The proof is read from the request itself rather than from this decoded parameter, so every protected operation is covered whether or not it declares it.

## Responses

### 200 OK

Every signal over the window, judged.

Content type: `application/json`

Headers:
- `Cache-Control` = `no-store`

Every signal of the threat catalog counted over one window, each judged
against its threshold and the equal window before. The window is the
one asked for widened to
whole buckets, and is echoed with the bucket, so a sparkline labels
exactly the buckets it was given.

The overview counts audit records, so it sees what the deployment's
audit level records: a refusal is recorded at the refusal level
whatever its action's own, and the records the edge coalesces count
once per summary. An answer is cached per organization for at least
the dashboard's shortest refresh interval, and longer over a longer
window.

- `from` (string (date-time), required): The first bucket's start.
- `to` (string (date-time), required): The last bucket's end.
- `bucket` (enum, required): A bucket length counts are grouped by, each allowed up to a window: `1m` up to 2 hours, `10m` up to 2 days, `1h` up to 31 days and `1d` up to the 90-day maximum. Buckets are UTC, a day's included. One of: `"1m"`, `"10m"`, `"1h"`, `"1d"`.
- `baseline_from` (string (date-time), required): The start of the equal window before, which ends at `from`.
- `signals` (array of objects, required): Every signal of the catalog, in its display order. Constraints: at most 64 items. No other properties are accepted.

  Each item: One signal over the window: how many records it counted, how many the equal window before held, the counts per bucket for a sparkline, the status that judges them, and the threshold and references that explain the judgement. `filter` is absent when no filter lists what the signal counts: a signal counted in the zones the second-factor policy spares counts nothing for an organization whose policy spares none.
  - `kind` (enum, required): One signal of the threat overview: a closed set of audit actions and outcomes counted over the window. Translated under `threats.signal.<value>`. One of: `"sign_in_failures"`, `"spared_zone_sign_in_failures"`, `"account_locks"`, `"sign_in_throttles"`, `"recovery_refusals"`, `"registration_refusals"`, `"second_factor_failures"`, `"second_factor_locks"`, `"token_grant_refusals"`, `"access_token_refusals"`, `"client_authentication_failures"`, `"authorization_refusals"`, `"device_code_guesses"`, `"suspicious_clients"`, `"admin_access_denials"`, `"request_screening_refusals"`.

    **Compatibility:** closed. A client should render a kind it does not
    know by its count and status alone.
  - `category` (enum, required): The group a signal is shown under: guessing credentials, guessing the second factor, misusing tokens and clients at the protocol endpoints, registering clients, probing the privileged API, and malformed traffic turned away at the edge. One of: `"credentials"`, `"second_factor"`, `"tokens"`, `"clients"`, `"admin"`, `"edge"`.
  - `severity` (enum, required): How much an event matters, lowest first. Assigned per action, and an occurrence may raise it but never lower it. A refusal or a server fault is raised to at least `warning` whatever its action's default, so `severity >= warning` selects everything that did not go as asked; a protocol step that only looks like a failure (`authorization_pending`, `use_dpop_nonce`, `mfa_required`, `passkey_offered`, `login_required`, `interaction_required`, `consent_required`, `account_selection_required`) keeps its action's default. One of: `"info"`, `"notice"`, `"warning"`, `"critical"`.
  - `count` (integer (int64), required): The records counted in the window. Constraints: at least 0.
  - `baseline_count` (integer (int64), required): The records counted in the equal window ending where this one starts. Constraints: at least 0.
  - `counts` (array of integers (int64), required): One count per bucket from `from` to `to`, zero where nothing matched. Constraints: each item: at least 0.
  - `status` (enum, required): How a signal's count reads against its threshold: `quiet` when nothing was counted, `normal` under every threshold, `elevated` at or over the elevated rate or several times the window before, `critical` at or over the critical rate. One of: `"quiet"`, `"normal"`, `"elevated"`, `"critical"`.
  - `rule` (enum, required): Which part of the threshold decided the status: `critical_rate` or `elevated_rate` when the rate per hour over the whole window reached that rate, `baseline` when the count reached `baseline_floor` and `baseline_ratio` times the window before, `under_threshold` when it was counted and no rule was met, and `none` when nothing was counted. One of: `"none"`, `"critical_rate"`, `"elevated_rate"`, `"baseline"`, `"under_threshold"`.
  - `rate_per_hour` (number, required): The count as a rate per hour over the whole window: what the threshold's rates are read against. Constraints: at least 0.
  - `threshold` (object, required): The recommended measurement a signal is judged by. The rates are per hour over the whole window, so one threshold means the same over a quarter of an hour and over a month; the baseline rule raises the status to `elevated` when the count is at least `baseline_ratio` times the count of the equal window before, once it reaches `baseline_floor`. No other properties are accepted.
    - `elevated_per_hour` (number, required): Constraints: at least 0.
    - `critical_per_hour` (number, required): Constraints: at least 0.
    - `baseline_ratio` (number, required): Constraints: at least 1.
    - `baseline_floor` (integer (int64), required): Constraints: at least 0.
  - `references` (array of objects, required): Where the threat a signal counts is described. Constraints: at most 8 items. No other properties are accepted.
    - `framework` (string, required): `MITRE ATT&CK`, `OWASP Automated Threats`, `RFC 9700`, … Constraints: at most 64 characters.
    - `id` (string, required): The technique, threat or section within it. Constraints: at most 64 characters.
    - `url` (string (uri), required): Constraints: at most 512 characters.
  - `filter` (object, optional): The audit list's filters that list exactly the records the signal counted, for the drill-down from a tile to the log: values of its `action`, `outcome` and `network_zone` parameters. An empty `outcome` means every outcome. `network_zone` is present on a signal counted in the zones the organization's second-factor policy spares, and names them. No other properties are accepted.
    - `action` (array of enums, required): The event type — what was attempted. Append-only: an action is never renamed once shipped, because a rename orphans every stored record and every SIEM rule matching on it. One of: `"admin.access.denied"`, `"audit.counts.read"`, `"audit.log.read"`, `"audit.ranking.read"`, `"auth.account.locked"`, `"auth.email_verification.completed"`, `"auth.email_verification.requested"`, `"auth.invitation.accepted"`, `"auth.password_reset.completed"`, `"auth.password_reset.requested"`, `"auth.rate_limit.triggered"`, `"auth.registration.completed"`, `"auth.sign_in.alerted"`, `"auth.sign_in.completed"`, `"auth.sign_out.completed"`, `"branding.applied"`, `"branding.deleted"`, `"broker_membership.accepted"`, `"broker_membership.clients_set"`, `"broker_membership.ended"`, `"broker_membership.invited"`, `"broker_membership.listed"`, `"client.adopted"`, `"client.applied"`, `"client.configuration.read"`, `"client.configured"`, `"client.deleted"`, `"client.deregistered"`, `"client.listed"`, `"client.name.suspicious"`, `"client.provisioned"`, `"client.read"`, `"client.registered"`, `"client.registration.attempted"`, `"client.secret.issued"`, `"client.usage.read"`, `"email_domain.claimed"`, `"email_domain.listed"`, `"email_domain.lost"`, `"email_domain.removed"`, `"email_domain.verified"`, `"http.cleartext_credential.received"`, `"http.forwarding.ignored"`, `"http.header.repeated"`, `"http.request.screened"`, `"http.request.served"`, `"identity_provider.applied"`, `"identity_provider.deleted"`, `"identity_provider.listed"`, `"ldap_directory.applied"`, `"ldap_directory.deleted"`, `"mfa.email.activated"`, `"mfa.email.challenge_started"`, `"mfa.email.enrollment_started"`, `"mfa.email.revoked"`, `"mfa.email.verified"`, `"mfa.factor.locked"`, `"mfa.passkey.challenge_started"`, `"mfa.passkey.enrollment_started"`, `"mfa.passkey.offer_declined"`, `"mfa.passkey.registered"`, `"mfa.passkey.verified"`, `"mfa.recovery_code.consumed"`, `"mfa.recovery_codes.acknowledged"`, `"mfa.recovery_codes.regenerated"`, `"mfa.request.authenticated"`, `"mfa.status.read"`, `"mfa.totp.activated"`, `"mfa.totp.disabled"`, `"mfa.totp.enrollment_started"`, `"mfa.totp.verified"`, `"oauth.authorization.requested"`, `"oauth.client_authentication.attempted"`, `"oauth.consent.decided"`, `"oauth.consent.revoked"`, `"oauth.device.decided"`, `"oauth.device.redeemed"`, `"oauth.device.requested"`, `"oauth.device.user_code.attempted"`, `"oauth.token.introspected"`, `"oauth.token.issued"`, `"oauth.token.presented"`, `"oauth.token.refreshed"`, `"oauth.token.revoked"`, `"oidc.logout.frontchannel.rendered"`, `"oidc.logout.initiated"`, `"oidc.logout.participant.added"`, `"oidc.logout.participant.skipped"`, `"oidc.logout.token.delivered"`, `"oidc.userinfo.read"`, `"organization.created"`, `"organization.deleted"`, `"organization.listed"`, `"organization.mail.tested"`, `"organization.read"`, `"organization.route.attempted"`, `"organization.snapshot.read"`, `"organization.updated"`, `"resource_problem.listed"`, `"resource_problem.read"`, `"resource_status.reported"`, `"role.granted"`, `"role.revoked"`, `"session.created"`, `"session.history.listed"`, `"session.listed"`, `"session.presented"`, `"session.revoked"`, `"system.admin.bootstrapped"`, `"system.audit.checkpoint"`, `"system.audit.configured"`, `"system.audit.degraded"`, `"system.audit.overflow"`, `"system.audit.partition_created"`, `"system.audit.partition_dropped"`, `"system.audit.recovered"`, `"system.audit.write_delayed"`, `"system.audit.write_failed"`, `"system.debug.accessed"`, `"system.dependency.degraded"`, `"system.dependency.recovered"`, `"system.keys.loaded"`, `"system.migration.applied"`, `"system.session.reaped"`, `"system.signing_key.created"`, `"system.signing_key.dropped"`, `"system.started"`, `"system.stopped"`, `"system.transport.configured"`, `"threats.overview.read"`, `"user.blocked"`, `"user.created"`, `"user.deleted"`, `"user.devices.listed"`, `"user.identities.listed"`, `"user.invitation.sent"`, `"user.listed"`, `"user.password.changed"`, `"user.password_change.required"`, `"user.password_reset.sent"`, `"user.reactivated"`, `"user.read"`, `"user.remembered_browsers.forgotten"`, `"user.suspended"`, `"user.unlocked"`, `"user.updated"`. Constraints: at most 16 items.

      The outcome is deliberately NOT part of the name. `auth.sign_in.completed`
      with `outcome: failure` is a failed sign-in; there is no
      `auth.sign_in.failed`. Encoding it would double this list, the catalog and
      every translation file.

      **Translation key:** the action verbatim in the `auditEvents` namespace —
      `auditEvents:user.password.changed`. Because i18next splits keys on `.`,
      a locale file nests naturally by segment. The catalog endpoint publishes
      the same key as `i18n_key` so a client need not re-derive it.

      **Compatibility:** this is a CLOSED enum, and that has a cost worth
      stating plainly. A client generated against one version of this document
      will reject an entire audit page — not merely one record — the first time
      the server emits an action added after that client was built. Regenerate
      on upgrade, or decode the field as a plain string. It is enumerated
      anyway because the alternative left every consumer unable to know the
      translatable vocabulary without calling the catalog endpoint at runtime.
    - `outcome` (array of enums, required): How an attempt ended. `denied` is separated from `failure` because "you were not allowed" and "you got it wrong" are different security signals — a cluster of the former is what a SIEM alerts on. `error` marks a failure attributable to the server, so an operator can tell "users are getting it wrong" from "we are broken". The server enforces the pairing: `error` always carries the reason `internal_error` or `unavailable`, and those two reasons never appear under any other outcome. One of: `"success"`, `"failure"`, `"denied"`, `"error"`. Constraints: at most 4 items.
    - `network_zone` (array of strings, optional): Constraints: at most 64 items; each item: at most 63 characters.

### 400 Bad Request

The query was invalid — a time window that ends before it starts or spans more than 90 days, or longer than the bucket asked for allows (`window_too_large`).

Content type: `application/problem+json`

RFC 9457 (formerly RFC 7807) problem details (application/problem+json). `code` is a stable machine-readable slug for the problem kind (it mirrors the last path segment of `type`), so consumers can branch on it without parsing prose. `type` is `https://nauthera.io/problems/<code>`, which resolves to the code's runbook: why it happened, who is affected and what to do (RFC 9457 §3.1.1). A problem without a code has `about:blank`. `errors` is present on validation failures and lists every offending field.

- `title` (string, required): Example: `"Request validation failed"`.
- `status` (integer, required): Example: `400`.
- `type` (string (uri), optional): Example: `"https://nauthera.io/problems/validation_error"`.
- `detail` (string, optional): Example: `"One or more fields did not satisfy the API schema."`.
- `code` (enum, optional): The kind of problem, as a stable machine-readable slug a client branches on and translates rather than parsing `title` or `detail`, which are English prose for logs. A problem whose status says everything the server knows carries no `code`. One of: `"invalid_request"`, `"invalid_credentials"`, `"forbidden"`, `"unauthorized"`, `"insufficient_user_authentication"`, `"protected_account"`, `"password_held_by_directory"`, `"last_role_administrator"`, `"invalid_code"`, `"too_many_requests"`, `"too_many_attempts"`, `"account_locked"`, `"account_unavailable"`, `"already_enrolled"`, `"registration_disabled"`, `"registration_conflict"`, `"captcha_failed"`, `"invalid_reset_link"`, `"password_reused"`, `"password_too_short"`, `"password_too_long"`, `"password_compromised"`, `"invalid_verification_link"`, `"invalid_invitation_link"`, `"mail_relay_missing"`, `"email_unverified"`, `"not_found"`, `"conflict"`, `"unavailable"`, `"busy"`, `"window_too_large"`, `"too_many_series"`, `"internal_error"`, `"rate_limited"`, `"malformed"`, `"body_too_large"`, `"required"`, `"validation_error"`, `"unknown_org"`, `"invalid_token"`, `"invalid_dpop_proof"`, `"use_dpop_nonce"`, `"server_error"`.

  `validation_error` is the one code whose message is not a sentence about
  the code itself: the request failed the schema, and the specifics are
  the `errors` list — one entry per offending field — which a form renders
  on those fields. `required` and `malformed` are spelled like two of the
  per-field violation codes (`FieldError.code`) but mean something else;
  the two vocabularies are told apart by position, never by spelling.

  **Compatibility:** this is a CLOSED enum, with the same cost as
  `AuditAction`: a client generated against an older version of this
  document rejects a problem carrying a code added after it was built.
  Regenerate on upgrade, or decode the field as a plain string. It is
  enumerated anyway so that what a client must translate is knowable
  from the contract alone.
- `instance` (string, optional): Example: `"/introspect"`.
- `request_id` (string, optional): Example: `"8d94ed49-1caf-4ab3-9594-557142f2d023"`.
- `trace_id` (string, optional): Distributed-trace id (hex) for correlating this response with traces and logs. Present only when tracing is enabled and the request was recorded. Opaque and safe to log/share. Example: `"4bf92f3577b34da6a3ce929d0e0e4736"`.
- `errors` (array of objects, optional): Field-level violations (present for validation errors).

  Each item: A single field-level validation violation.
  - `field` (string, required): Offending field, dotted for nested bodies (e.g. child.id). Example: `"token_type_hint"`.
  - `code` (string, required): Machine-readable violation code: required, too_short, too_long, pattern, invalid_format, not_allowed, minimum, maximum, multiple_of, too_few, too_many, not_unique, malformed. Example: `"not_allowed"`.
  - `message` (string, required): Example: `"field token_type_hint must be one of [access_token, refresh_token]"`.

### 401 Unauthorized

Problem details (RFC 9457) with an RFC 6750 / RFC 9449 challenge.

Content type: `application/problem+json`

Headers:
- `Cache-Control` = `no-store`
- `WWW-Authenticate` (string)
- `DPoP-Nonce` (string)

RFC 9457 (formerly RFC 7807) problem details (application/problem+json). `code` is a stable machine-readable slug for the problem kind (it mirrors the last path segment of `type`), so consumers can branch on it without parsing prose. `type` is `https://nauthera.io/problems/<code>`, which resolves to the code's runbook: why it happened, who is affected and what to do (RFC 9457 §3.1.1). A problem without a code has `about:blank`. `errors` is present on validation failures and lists every offending field.

- `title` (string, required): Example: `"Request validation failed"`.
- `status` (integer, required): Example: `400`.
- `type` (string (uri), optional): Example: `"https://nauthera.io/problems/validation_error"`.
- `detail` (string, optional): Example: `"One or more fields did not satisfy the API schema."`.
- `code` (enum, optional): The kind of problem, as a stable machine-readable slug a client branches on and translates rather than parsing `title` or `detail`, which are English prose for logs. A problem whose status says everything the server knows carries no `code`. One of: `"invalid_request"`, `"invalid_credentials"`, `"forbidden"`, `"unauthorized"`, `"insufficient_user_authentication"`, `"protected_account"`, `"password_held_by_directory"`, `"last_role_administrator"`, `"invalid_code"`, `"too_many_requests"`, `"too_many_attempts"`, `"account_locked"`, `"account_unavailable"`, `"already_enrolled"`, `"registration_disabled"`, `"registration_conflict"`, `"captcha_failed"`, `"invalid_reset_link"`, `"password_reused"`, `"password_too_short"`, `"password_too_long"`, `"password_compromised"`, `"invalid_verification_link"`, `"invalid_invitation_link"`, `"mail_relay_missing"`, `"email_unverified"`, `"not_found"`, `"conflict"`, `"unavailable"`, `"busy"`, `"window_too_large"`, `"too_many_series"`, `"internal_error"`, `"rate_limited"`, `"malformed"`, `"body_too_large"`, `"required"`, `"validation_error"`, `"unknown_org"`, `"invalid_token"`, `"invalid_dpop_proof"`, `"use_dpop_nonce"`, `"server_error"`.

  `validation_error` is the one code whose message is not a sentence about
  the code itself: the request failed the schema, and the specifics are
  the `errors` list — one entry per offending field — which a form renders
  on those fields. `required` and `malformed` are spelled like two of the
  per-field violation codes (`FieldError.code`) but mean something else;
  the two vocabularies are told apart by position, never by spelling.

  **Compatibility:** this is a CLOSED enum, with the same cost as
  `AuditAction`: a client generated against an older version of this
  document rejects a problem carrying a code added after it was built.
  Regenerate on upgrade, or decode the field as a plain string. It is
  enumerated anyway so that what a client must translate is knowable
  from the contract alone.
- `instance` (string, optional): Example: `"/introspect"`.
- `request_id` (string, optional): Example: `"8d94ed49-1caf-4ab3-9594-557142f2d023"`.
- `trace_id` (string, optional): Distributed-trace id (hex) for correlating this response with traces and logs. Present only when tracing is enabled and the request was recorded. Opaque and safe to log/share. Example: `"4bf92f3577b34da6a3ce929d0e0e4736"`.
- `errors` (array of objects, optional): Field-level violations (present for validation errors).

  Each item: A single field-level validation violation.
  - `field` (string, required): Offending field, dotted for nested bodies (e.g. child.id). Example: `"token_type_hint"`.
  - `code` (string, required): Machine-readable violation code: required, too_short, too_long, pattern, invalid_format, not_allowed, minimum, maximum, multiple_of, too_few, too_many, not_unique, malformed. Example: `"not_allowed"`.
  - `message` (string, required): Example: `"field token_type_hint must be one of [access_token, refresh_token]"`.

### 403 Forbidden

Problem details (RFC 9457) with an RFC 6750 / RFC 9449 challenge.

Content type: `application/problem+json`

Headers:
- `Cache-Control` = `no-store`
- `WWW-Authenticate` (string)
- `DPoP-Nonce` (string)

RFC 9457 (formerly RFC 7807) problem details (application/problem+json). `code` is a stable machine-readable slug for the problem kind (it mirrors the last path segment of `type`), so consumers can branch on it without parsing prose. `type` is `https://nauthera.io/problems/<code>`, which resolves to the code's runbook: why it happened, who is affected and what to do (RFC 9457 §3.1.1). A problem without a code has `about:blank`. `errors` is present on validation failures and lists every offending field.

- `title` (string, required): Example: `"Request validation failed"`.
- `status` (integer, required): Example: `400`.
- `type` (string (uri), optional): Example: `"https://nauthera.io/problems/validation_error"`.
- `detail` (string, optional): Example: `"One or more fields did not satisfy the API schema."`.
- `code` (enum, optional): The kind of problem, as a stable machine-readable slug a client branches on and translates rather than parsing `title` or `detail`, which are English prose for logs. A problem whose status says everything the server knows carries no `code`. One of: `"invalid_request"`, `"invalid_credentials"`, `"forbidden"`, `"unauthorized"`, `"insufficient_user_authentication"`, `"protected_account"`, `"password_held_by_directory"`, `"last_role_administrator"`, `"invalid_code"`, `"too_many_requests"`, `"too_many_attempts"`, `"account_locked"`, `"account_unavailable"`, `"already_enrolled"`, `"registration_disabled"`, `"registration_conflict"`, `"captcha_failed"`, `"invalid_reset_link"`, `"password_reused"`, `"password_too_short"`, `"password_too_long"`, `"password_compromised"`, `"invalid_verification_link"`, `"invalid_invitation_link"`, `"mail_relay_missing"`, `"email_unverified"`, `"not_found"`, `"conflict"`, `"unavailable"`, `"busy"`, `"window_too_large"`, `"too_many_series"`, `"internal_error"`, `"rate_limited"`, `"malformed"`, `"body_too_large"`, `"required"`, `"validation_error"`, `"unknown_org"`, `"invalid_token"`, `"invalid_dpop_proof"`, `"use_dpop_nonce"`, `"server_error"`.

  `validation_error` is the one code whose message is not a sentence about
  the code itself: the request failed the schema, and the specifics are
  the `errors` list — one entry per offending field — which a form renders
  on those fields. `required` and `malformed` are spelled like two of the
  per-field violation codes (`FieldError.code`) but mean something else;
  the two vocabularies are told apart by position, never by spelling.

  **Compatibility:** this is a CLOSED enum, with the same cost as
  `AuditAction`: a client generated against an older version of this
  document rejects a problem carrying a code added after it was built.
  Regenerate on upgrade, or decode the field as a plain string. It is
  enumerated anyway so that what a client must translate is knowable
  from the contract alone.
- `instance` (string, optional): Example: `"/introspect"`.
- `request_id` (string, optional): Example: `"8d94ed49-1caf-4ab3-9594-557142f2d023"`.
- `trace_id` (string, optional): Distributed-trace id (hex) for correlating this response with traces and logs. Present only when tracing is enabled and the request was recorded. Opaque and safe to log/share. Example: `"4bf92f3577b34da6a3ce929d0e0e4736"`.
- `errors` (array of objects, optional): Field-level violations (present for validation errors).

  Each item: A single field-level validation violation.
  - `field` (string, required): Offending field, dotted for nested bodies (e.g. child.id). Example: `"token_type_hint"`.
  - `code` (string, required): Machine-readable violation code: required, too_short, too_long, pattern, invalid_format, not_allowed, minimum, maximum, multiple_of, too_few, too_many, not_unique, malformed. Example: `"not_allowed"`.
  - `message` (string, required): Example: `"field token_type_hint must be one of [access_token, refresh_token]"`.

### 429 Too Many Requests

Too many requests.

Content type: `application/problem+json`

RFC 9457 (formerly RFC 7807) problem details (application/problem+json). `code` is a stable machine-readable slug for the problem kind (it mirrors the last path segment of `type`), so consumers can branch on it without parsing prose. `type` is `https://nauthera.io/problems/<code>`, which resolves to the code's runbook: why it happened, who is affected and what to do (RFC 9457 §3.1.1). A problem without a code has `about:blank`. `errors` is present on validation failures and lists every offending field.

- `title` (string, required): Example: `"Request validation failed"`.
- `status` (integer, required): Example: `400`.
- `type` (string (uri), optional): Example: `"https://nauthera.io/problems/validation_error"`.
- `detail` (string, optional): Example: `"One or more fields did not satisfy the API schema."`.
- `code` (enum, optional): The kind of problem, as a stable machine-readable slug a client branches on and translates rather than parsing `title` or `detail`, which are English prose for logs. A problem whose status says everything the server knows carries no `code`. One of: `"invalid_request"`, `"invalid_credentials"`, `"forbidden"`, `"unauthorized"`, `"insufficient_user_authentication"`, `"protected_account"`, `"password_held_by_directory"`, `"last_role_administrator"`, `"invalid_code"`, `"too_many_requests"`, `"too_many_attempts"`, `"account_locked"`, `"account_unavailable"`, `"already_enrolled"`, `"registration_disabled"`, `"registration_conflict"`, `"captcha_failed"`, `"invalid_reset_link"`, `"password_reused"`, `"password_too_short"`, `"password_too_long"`, `"password_compromised"`, `"invalid_verification_link"`, `"invalid_invitation_link"`, `"mail_relay_missing"`, `"email_unverified"`, `"not_found"`, `"conflict"`, `"unavailable"`, `"busy"`, `"window_too_large"`, `"too_many_series"`, `"internal_error"`, `"rate_limited"`, `"malformed"`, `"body_too_large"`, `"required"`, `"validation_error"`, `"unknown_org"`, `"invalid_token"`, `"invalid_dpop_proof"`, `"use_dpop_nonce"`, `"server_error"`.

  `validation_error` is the one code whose message is not a sentence about
  the code itself: the request failed the schema, and the specifics are
  the `errors` list — one entry per offending field — which a form renders
  on those fields. `required` and `malformed` are spelled like two of the
  per-field violation codes (`FieldError.code`) but mean something else;
  the two vocabularies are told apart by position, never by spelling.

  **Compatibility:** this is a CLOSED enum, with the same cost as
  `AuditAction`: a client generated against an older version of this
  document rejects a problem carrying a code added after it was built.
  Regenerate on upgrade, or decode the field as a plain string. It is
  enumerated anyway so that what a client must translate is knowable
  from the contract alone.
- `instance` (string, optional): Example: `"/introspect"`.
- `request_id` (string, optional): Example: `"8d94ed49-1caf-4ab3-9594-557142f2d023"`.
- `trace_id` (string, optional): Distributed-trace id (hex) for correlating this response with traces and logs. Present only when tracing is enabled and the request was recorded. Opaque and safe to log/share. Example: `"4bf92f3577b34da6a3ce929d0e0e4736"`.
- `errors` (array of objects, optional): Field-level violations (present for validation errors).

  Each item: A single field-level validation violation.
  - `field` (string, required): Offending field, dotted for nested bodies (e.g. child.id). Example: `"token_type_hint"`.
  - `code` (string, required): Machine-readable violation code: required, too_short, too_long, pattern, invalid_format, not_allowed, minimum, maximum, multiple_of, too_few, too_many, not_unique, malformed. Example: `"not_allowed"`.
  - `message` (string, required): Example: `"field token_type_hint must be one of [access_token, refresh_token]"`.

### 503 Service Unavailable

The server is computing as many aggregates as it allows at once, or this one did not finish within its deadline (`busy`); retry after Retry-After. Also answered when audit logging is not enabled (`unavailable`).

Content type: `application/problem+json`

Headers:
- `Retry-After` (string)

RFC 9457 (formerly RFC 7807) problem details (application/problem+json). `code` is a stable machine-readable slug for the problem kind (it mirrors the last path segment of `type`), so consumers can branch on it without parsing prose. `type` is `https://nauthera.io/problems/<code>`, which resolves to the code's runbook: why it happened, who is affected and what to do (RFC 9457 §3.1.1). A problem without a code has `about:blank`. `errors` is present on validation failures and lists every offending field.

- `title` (string, required): Example: `"Request validation failed"`.
- `status` (integer, required): Example: `400`.
- `type` (string (uri), optional): Example: `"https://nauthera.io/problems/validation_error"`.
- `detail` (string, optional): Example: `"One or more fields did not satisfy the API schema."`.
- `code` (enum, optional): The kind of problem, as a stable machine-readable slug a client branches on and translates rather than parsing `title` or `detail`, which are English prose for logs. A problem whose status says everything the server knows carries no `code`. One of: `"invalid_request"`, `"invalid_credentials"`, `"forbidden"`, `"unauthorized"`, `"insufficient_user_authentication"`, `"protected_account"`, `"password_held_by_directory"`, `"last_role_administrator"`, `"invalid_code"`, `"too_many_requests"`, `"too_many_attempts"`, `"account_locked"`, `"account_unavailable"`, `"already_enrolled"`, `"registration_disabled"`, `"registration_conflict"`, `"captcha_failed"`, `"invalid_reset_link"`, `"password_reused"`, `"password_too_short"`, `"password_too_long"`, `"password_compromised"`, `"invalid_verification_link"`, `"invalid_invitation_link"`, `"mail_relay_missing"`, `"email_unverified"`, `"not_found"`, `"conflict"`, `"unavailable"`, `"busy"`, `"window_too_large"`, `"too_many_series"`, `"internal_error"`, `"rate_limited"`, `"malformed"`, `"body_too_large"`, `"required"`, `"validation_error"`, `"unknown_org"`, `"invalid_token"`, `"invalid_dpop_proof"`, `"use_dpop_nonce"`, `"server_error"`.

  `validation_error` is the one code whose message is not a sentence about
  the code itself: the request failed the schema, and the specifics are
  the `errors` list — one entry per offending field — which a form renders
  on those fields. `required` and `malformed` are spelled like two of the
  per-field violation codes (`FieldError.code`) but mean something else;
  the two vocabularies are told apart by position, never by spelling.

  **Compatibility:** this is a CLOSED enum, with the same cost as
  `AuditAction`: a client generated against an older version of this
  document rejects a problem carrying a code added after it was built.
  Regenerate on upgrade, or decode the field as a plain string. It is
  enumerated anyway so that what a client must translate is knowable
  from the contract alone.
- `instance` (string, optional): Example: `"/introspect"`.
- `request_id` (string, optional): Example: `"8d94ed49-1caf-4ab3-9594-557142f2d023"`.
- `trace_id` (string, optional): Distributed-trace id (hex) for correlating this response with traces and logs. Present only when tracing is enabled and the request was recorded. Opaque and safe to log/share. Example: `"4bf92f3577b34da6a3ce929d0e0e4736"`.
- `errors` (array of objects, optional): Field-level violations (present for validation errors).

  Each item: A single field-level validation violation.
  - `field` (string, required): Offending field, dotted for nested bodies (e.g. child.id). Example: `"token_type_hint"`.
  - `code` (string, required): Machine-readable violation code: required, too_short, too_long, pattern, invalid_format, not_allowed, minimum, maximum, multiple_of, too_few, too_many, not_unique, malformed. Example: `"not_allowed"`.
  - `message` (string, required): Example: `"field token_type_hint must be one of [access_token, refresh_token]"`.

### Error

Problem details (RFC 9457) with an RFC 6750 / RFC 9449 challenge.

Content type: `application/problem+json`

Headers:
- `Cache-Control` = `no-store`
- `WWW-Authenticate` (string)
- `DPoP-Nonce` (string)

RFC 9457 (formerly RFC 7807) problem details (application/problem+json). `code` is a stable machine-readable slug for the problem kind (it mirrors the last path segment of `type`), so consumers can branch on it without parsing prose. `type` is `https://nauthera.io/problems/<code>`, which resolves to the code's runbook: why it happened, who is affected and what to do (RFC 9457 §3.1.1). A problem without a code has `about:blank`. `errors` is present on validation failures and lists every offending field.

- `title` (string, required): Example: `"Request validation failed"`.
- `status` (integer, required): Example: `400`.
- `type` (string (uri), optional): Example: `"https://nauthera.io/problems/validation_error"`.
- `detail` (string, optional): Example: `"One or more fields did not satisfy the API schema."`.
- `code` (enum, optional): The kind of problem, as a stable machine-readable slug a client branches on and translates rather than parsing `title` or `detail`, which are English prose for logs. A problem whose status says everything the server knows carries no `code`. One of: `"invalid_request"`, `"invalid_credentials"`, `"forbidden"`, `"unauthorized"`, `"insufficient_user_authentication"`, `"protected_account"`, `"password_held_by_directory"`, `"last_role_administrator"`, `"invalid_code"`, `"too_many_requests"`, `"too_many_attempts"`, `"account_locked"`, `"account_unavailable"`, `"already_enrolled"`, `"registration_disabled"`, `"registration_conflict"`, `"captcha_failed"`, `"invalid_reset_link"`, `"password_reused"`, `"password_too_short"`, `"password_too_long"`, `"password_compromised"`, `"invalid_verification_link"`, `"invalid_invitation_link"`, `"mail_relay_missing"`, `"email_unverified"`, `"not_found"`, `"conflict"`, `"unavailable"`, `"busy"`, `"window_too_large"`, `"too_many_series"`, `"internal_error"`, `"rate_limited"`, `"malformed"`, `"body_too_large"`, `"required"`, `"validation_error"`, `"unknown_org"`, `"invalid_token"`, `"invalid_dpop_proof"`, `"use_dpop_nonce"`, `"server_error"`.

  `validation_error` is the one code whose message is not a sentence about
  the code itself: the request failed the schema, and the specifics are
  the `errors` list — one entry per offending field — which a form renders
  on those fields. `required` and `malformed` are spelled like two of the
  per-field violation codes (`FieldError.code`) but mean something else;
  the two vocabularies are told apart by position, never by spelling.

  **Compatibility:** this is a CLOSED enum, with the same cost as
  `AuditAction`: a client generated against an older version of this
  document rejects a problem carrying a code added after it was built.
  Regenerate on upgrade, or decode the field as a plain string. It is
  enumerated anyway so that what a client must translate is knowable
  from the contract alone.
- `instance` (string, optional): Example: `"/introspect"`.
- `request_id` (string, optional): Example: `"8d94ed49-1caf-4ab3-9594-557142f2d023"`.
- `trace_id` (string, optional): Distributed-trace id (hex) for correlating this response with traces and logs. Present only when tracing is enabled and the request was recorded. Opaque and safe to log/share. Example: `"4bf92f3577b34da6a3ce929d0e0e4736"`.
- `errors` (array of objects, optional): Field-level violations (present for validation errors).

  Each item: A single field-level validation violation.
  - `field` (string, required): Offending field, dotted for nested bodies (e.g. child.id). Example: `"token_type_hint"`.
  - `code` (string, required): Machine-readable violation code: required, too_short, too_long, pattern, invalid_format, not_allowed, minimum, maximum, multiple_of, too_few, too_many, not_unique, malformed. Example: `"not_allowed"`.
  - `message` (string, required): Example: `"field token_type_hint must be one of [access_token, refresh_token]"`.

## Example request

```bash
curl -g 'https://auth.example.com/v1/admin/orgs/{slug}/threats' \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

## Example response (200)

```json
{
  "from": "2026-01-15T09:30:00Z",
  "to": "2026-01-15T09:30:00Z",
  "bucket": "1m",
  "baseline_from": "2026-01-15T09:30:00Z",
  "signals": [
    {
      "kind": "sign_in_failures",
      "category": "credentials",
      "severity": "info",
      "count": 0,
      "baseline_count": 0,
      "counts": [
        0
      ],
      "status": "quiet",
      "rule": "none",
      "rate_per_hour": 0,
      "threshold": {
        "elevated_per_hour": 0,
        "critical_per_hour": 0,
        "baseline_ratio": 1,
        "baseline_floor": 0
      },
      "references": [
        {
          "framework": "string",
          "id": "string",
          "url": "https://example.com"
        }
      ]
    }
  ]
}
```
