> ## Documentation Index
> Fetch the complete documentation index at: https://docs.noresponse.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Retrieve an assessment

> Returns the latest version of one assessment. This is the authoritative read: use it to poll a `pending` answer or to refresh one a webhook told you about.

While the assessment is `pending`, or `partial` with work still running, the response carries `Retry-After`. Do not poll faster than it says.

An unknown, expired, malformed or another account's id all answer 404 `not_found`.

Requires the `assess` or `history` scope. `response_mode=detailed` also needs the `detailed` scope.



## OpenAPI

````yaml /openapi.json get /v1/assessments/{assessment_id}
openapi: 3.1.0
info:
  title: NoResponse API
  version: '1'
  description: >-
    The NoResponse API assesses a signup, login or purchase and answers with the
    account's one current risk: a 0 to 100 score, a decision for the flow
    (`allow`, `step_up`, `review` or `block`), the reasons behind it and the
    decision for each flow. The assessment's own facts, such as its status,
    confidence and incomplete sources, sit under `detail`.


    Authenticate every request with your API key as `Authorization: Bearer
    nrk_...`. Call the API only from your backend.


    Guides, SDKs and webhook verification are at
    [docs.noresponse.org](https://docs.noresponse.org/). Every error is an RFC
    9457 problem document; see
    [Errors](https://docs.noresponse.org/reference/errors).
servers:
  - url: https://api.noresponse.org
    description: Production
security:
  - tenantBearer: []
tags:
  - name: assess
    x-displayName: Assessments
    x-group: Assessments
    description: Create, read and list assessments, and report outcomes.
  - name: accounts
    x-displayName: Accounts
    x-group: Accounts
    description: >-
      Each of your accounts holds one current risk, and its assessments are its
      history.
  - name: usage
    x-displayName: Key usage
    x-group: Key usage
    description: >-
      Report usage of the API keys your signup gate issued, so a shared or
      stolen key raises its account's risk.
  - name: keys
    x-displayName: API keys
    x-group: API keys
    description: Rotate your own API key.
  - name: integrations
    x-displayName: Integrations
    x-group: Integrations
    description: >-
      Hosted endpoints that answer your WorkOS or Auth0 sign-up and sign-in
      hooks.
  - name: webhooks
    x-displayName: Webhooks
    x-group: Webhooks
    description: Your webhook endpoints, and the signed events NoResponse sends to them.
paths:
  /v1/assessments/{assessment_id}:
    get:
      tags:
        - assess
      summary: Retrieve an assessment
      description: >-
        Returns the latest version of one assessment. This is the authoritative
        read: use it to poll a `pending` answer or to refresh one a webhook told
        you about.


        While the assessment is `pending`, or `partial` with work still running,
        the response carries `Retry-After`. Do not poll faster than it says.


        An unknown, expired, malformed or another account's id all answer 404
        `not_found`.


        Requires the `assess` or `history` scope. `response_mode=detailed` also
        needs the `detailed` scope.
      operationId: getAssessment
      parameters:
        - $ref: '#/components/parameters/AssessmentId'
        - name: response_mode
          in: query
          required: false
          description: >-
            Optional standard or separately authorised detailed customer view;
            raw is rejected.
          schema:
            type: string
            enum:
              - standard
              - detailed
            default: standard
      responses:
        '200':
          $ref: '#/components/responses/AssessmentPolled'
        '400':
          $ref: '#/components/responses/InvalidQuery'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/WorkspaceForbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/RateLimited'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
      security:
        - tenantBearer: []
      x-codeSamples:
        - lang: curl
          label: cURL
          source: |
            curl --request GET \
              --url 'https://api.noresponse.org/v1/assessments/asm_01JA2Z8K6Q4V7W9XBCDEFGHJKM' \
              --header "Authorization: Bearer $NORESPONSE_API_KEY"
        - lang: typescript
          label: TypeScript
          source: |
            import { NoResponse } from "@noresponse/node";

            const noResponse = new NoResponse({
              apiKey: process.env["NORESPONSE_API_KEY"] ?? "",
            });

            async function run() {
              const result = await noResponse.assessments.get({
                assessmentId: "asm_01JA2Z8K6Q4V7W9XBCDEFGHJKM",
              });

              console.log(result);
            }

            run();
        - lang: python
          label: Python
          source: |
            from noresponse import NoResponse
            import os


            with NoResponse(
                api_key=os.getenv("NORESPONSE_API_KEY", ""),
            ) as no_response:

                res = no_response.assessments.get(assessment_id="asm_01JA2Z8K6Q4V7W9XBCDEFGHJKM")

                # Handle response
                print(res)
        - lang: go
          label: Go
          source: "package main\n\nimport(\n\t\"context\"\n\t\"os\"\n\tnoresponse \"github.com/noresponsehq/go/v5\"\n\t\"log\"\n)\n\nfunc main() {\n    ctx := context.Background()\n\n    s := noresponse.New(\n        noresponse.WithSecurity(os.Getenv(\"NORESPONSE_API_KEY\")),\n    )\n\n    res, err := s.Assessments.Get(ctx, \"asm_01JA2Z8K6Q4V7W9XBCDEFGHJKM\", nil)\n    if err != nil {\n        log.Fatal(err)\n    }\n    if res != nil {\n        // handle response\n    }\n}\n"
        - lang: java
          label: Java
          source: |
            package hello.world;

            import java.lang.Exception;
            import org.noresponse.NoResponse;
            import org.noresponse.models.errors.AuthenticationException;
            import org.noresponse.models.errors.BadRequestException;
            import org.noresponse.models.errors.ConflictException;
            import org.noresponse.models.errors.NotFoundException;
            import org.noresponse.models.errors.PermissionDeniedException;
            import org.noresponse.models.errors.RateLimitException;
            import org.noresponse.models.operations.GetAssessmentResponse;

            public class Application {

                public static void main(String[] args) throws Exception {

                    NoResponse sdk = NoResponse.builder()
                            .apiKey(System.getenv().getOrDefault("NORESPONSE_API_KEY", ""))
                        .build();

                    GetAssessmentResponse res = sdk.assessments().get()
                            .assessmentId("asm_01JA2Z8K6Q4V7W9XBCDEFGHJKM")
                            .call();

                    if (res.assessment().isPresent()) {
                        System.out.println(res.assessment().get());
                    }
                }
            }
        - lang: csharp
          label: C#
          source: >
            using NoResponse;

            using NoResponse.Models.Shared;

            using System;


            var sdk = new NoResponseClient(apiKey:
            Environment.GetEnvironmentVariable("NORESPONSE_API_KEY"));


            var res = await sdk.Assessments.GetAsync(assessmentId:
            "asm_01JA2Z8K6Q4V7W9XBCDEFGHJKM");


            // handle response
        - lang: php
          label: PHP
          source: |
            <?php

            declare(strict_types=1);

            require 'vendor/autoload.php';

            use NoResponse;

            $sdk = NoResponse\NoResponseClient::builder()
                ->setSecurity(
                    getenv('NORESPONSE_API_KEY') ?: ''
                )
                ->build();



            $response = $sdk->assessments->get(
                assessmentId: 'asm_01JA2Z8K6Q4V7W9XBCDEFGHJKM'
            );

            if ($response->assessment !== null) {
                // handle response
            }
        - lang: ruby
          label: Ruby
          source: >
            require 'noresponse'


            Models = ::NoResponse::Models

            s = ::NoResponse::NoResponseClient.new(
              api_key: ENV.fetch('NORESPONSE_API_KEY', '')
            )

            res = s.assessments.get(assessment_id:
            'asm_01JA2Z8K6Q4V7W9XBCDEFGHJKM')


            unless res.nil?
              # handle response
            end
components:
  parameters:
    AssessmentId:
      name: assessment_id
      in: path
      required: true
      schema:
        type: string
        pattern: ^asm_[0-9A-HJKMNP-TV-Z]{26}$
        description: >-
          Opaque, server-assigned assessment id: 'asm_' and a 26-character
          Crockford base32 ULID. Unique within the workspace; another
          workspace's assessment id answers 404.
        not:
          description: >-
            A line feed anywhere, refused with `not` beside every anchored
            pattern.
          pattern: \n
      description: >-
        Path segment, matched case-sensitively. A value that does not match the
        assessment_id shape answers 404, not 400.
  responses:
    AssessmentPolled:
      description: >-
        The latest assessment_version. Retry-After is present while a source is
        still continuing.
      headers:
        Cache-Control:
          schema:
            type: string
            const: no-store
          required: true
        Retry-After:
          description: >-
            Whole seconds to wait before polling again. Present on a partial
            answer while a source is still continuing.
          schema:
            type: string
            pattern: >-
              ^(?:[1-9]|[1-9][0-9]|[1-9][0-9]{2}|[12][0-9]{3}|3[0-5][0-9]{2}|3600)$
            description: Whole decimal seconds; wait at least this long.
          required: false
        X-Request-ID:
          description: The request correlation id, 32 lowercase hexadecimal characters.
          schema:
            type: string
            pattern: ^[0-9a-f]{32}$
            not:
              pattern: \n
          required: true
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Assessment'
          examples:
            complete:
              value:
                schema_version: '1'
                id: asm_01JB3C4D5E6F7G8H9JKMNPQRST
                status: complete
                flow: account_creation
                depth: full
                account:
                  schema_version: '1'
                  id: acct_8412
                  risk:
                    score: 0
                    decision: allow
                    reasons:
                      - code: voip_number
                        weight: 25
                        identifier: phone
                      - code: breach_cooccurrence
                        weight: -10
                        identifier: phone
                      - code: breach_name_match
                        weight: -15
                        identifier: name
                      - code: established_accounts
                        weight: -15
                        identifier: email
                      - code: aged_identity
                        weight: -25
                        identifier: email
                  decisions_by_flow:
                    account_creation: allow
                    login: allow
                    purchase: allow
                  assessment_id: asm_01JB3C4D5E6F7G8H9JKMNPQRST
                  updated_at: '2026-10-18T11:00:04.000Z'
                detail:
                  schema_version: '1'
                  assessment_id: asm_01JB3C4D5E6F7G8H9JKMNPQRST
                  account_id: acct_8412
                  request_id: req_01
                  status: complete
                  recommendation: allow
                  confidence: high
                  risk:
                    score: 0
                    band: low
                    recommendation: allow
                    block: false
                    confidence: high
                    policy_version: risk-2026-10.3
                    policy_basis: heuristic_unvalidated
                    reasons:
                      - code: voip_number
                        weight: 25
                        identifier: phone
                      - code: breach_cooccurrence
                        weight: -10
                        identifier: phone
                      - code: breach_name_match
                        weight: -15
                        identifier: name
                      - code: established_accounts
                        weight: -15
                        identifier: email
                      - code: aged_identity
                        weight: -25
                        identifier: email
                    summary:
                      email:
                        disposable: false
                        accounts_found: 6
                        breach:
                          found: true
                          breach_count: 7
                          first_year: 2013
                          last_year: 2021
                          exposed:
                            - email
                            - name
                            - password
                            - phone
                            - ip
                          in_credential_lists: false
                          recent_password_exposure: false
                          truncated: false
                      username:
                        accounts_found: 3
                        breach:
                          found: false
                          truncated: false
                      phone:
                        line_type: voip
                        country: US
                        report_count: 0
                      ip:
                        country: US
                        type: residential
                        seen_in_workspace: 1
                      consistency:
                        name: match
                        phone: match
                        ip: unknown
                        country: consistent
                    coverage:
                      answered: 14
                      failed: 1
                      pending: 0
                  incomplete_sources: []
                  policy_version: risk-2026-10.3
                  policy_basis: heuristic_unvalidated
                  assessment_version: 3
                  created_at: '2026-10-18T11:00:00.000Z'
                  updated_at: '2026-10-18T11:00:04.000Z'
                  expires_at: '2027-10-18T11:00:00.000Z'
                  timing:
                    deadline_ms: 500
                    elapsed_ms: 4000
            partial:
              value:
                schema_version: '1'
                id: asm_01JB3C4D5E6F7G8H9JKMNPQRST
                status: partial
                flow: account_creation
                depth: full
                account:
                  schema_version: '1'
                  id: acct_8412
                  risk:
                    score: 15
                    decision: allow
                    reasons:
                      - code: recent_password_exposure
                        weight: 15
                        identifier: email
                  decisions_by_flow:
                    account_creation: allow
                    login: allow
                    purchase: allow
                  assessment_id: asm_01JB3C4D5E6F7G8H9JKMNPQRST
                  updated_at: '2026-10-18T11:00:10.000Z'
                detail:
                  schema_version: '1'
                  assessment_id: asm_01JB3C4D5E6F7G8H9JKMNPQRST
                  account_id: acct_8412
                  request_id: req_01
                  status: partial
                  recommendation: allow
                  confidence: medium
                  risk:
                    score: 15
                    band: low
                    recommendation: allow
                    block: false
                    confidence: medium
                    policy_version: risk-2026-10.3
                    policy_basis: heuristic_unvalidated
                    reasons:
                      - code: recent_password_exposure
                        weight: 15
                        identifier: email
                    summary:
                      email:
                        disposable: false
                        accounts_found: 1
                        breach:
                          found: true
                          breach_count: 3
                          first_year: 2019
                          last_year: 2025
                          exposed:
                            - email
                            - password
                          recent_password_exposure: true
                          truncated: false
                      username:
                        breach:
                          found: true
                          breach_count: 25
                          truncated: true
                      consistency:
                        name: unknown
                    coverage:
                      answered: 5
                      failed: 1
                      pending: 0
                  incomplete_sources:
                    - lane: accounts
                      reason: timed_out
                  policy_version: risk-2026-10.3
                  policy_basis: heuristic_unvalidated
                  assessment_version: 2
                  created_at: '2026-10-18T11:00:00.000Z'
                  updated_at: '2026-10-18T11:00:10.000Z'
                  expires_at: '2027-10-18T11:00:00.000Z'
                  timing:
                    deadline_ms: 500
                    elapsed_ms: 10000
                  assessment_url: /v1/assessments/asm_01JB3C4D5E6F7G8H9JKMNPQRST
            pending:
              value:
                schema_version: '1'
                id: asm_01JA2Z8K6Q4V7W9XBCDEFGHJKM
                status: pending
                flow: account_creation
                depth: full
                detail:
                  schema_version: '1'
                  assessment_id: asm_01JA2Z8K6Q4V7W9XBCDEFGHJKM
                  account_id: acct_7f3a9c
                  request_id: req-2026-10-14-0001
                  policy_version: heuristic-2026-10.1
                  policy_basis: heuristic_unvalidated
                  assessment_version: 2
                  created_at: '2026-10-14T09:00:00.000Z'
                  updated_at: '2026-10-14T09:00:00.412Z'
                  expires_at: '2027-10-14T09:00:00.000Z'
                  timing:
                    deadline_ms: 300
                    elapsed_ms: 301
                  status: pending
                  confidence: unavailable
                  incomplete_sources:
                    - lane: accounts
                      reason: timed_out
                    - lane: breach
                      reason: timed_out
                  assessment_url: /v1/assessments/asm_01JA2Z8K6Q4V7W9XBCDEFGHJKM
            pending_known_account:
              value:
                schema_version: '1'
                id: asm_01JA2Z8K6Q4V7W9XBCDEFGHJKM
                status: pending
                flow: purchase
                depth: full
                account:
                  schema_version: '1'
                  id: acct_7f3a9c
                  risk:
                    score: 0
                    decision: allow
                    reasons:
                      - code: voip_number
                        weight: 25
                        identifier: phone
                      - code: breach_cooccurrence
                        weight: -10
                        identifier: phone
                      - code: breach_name_match
                        weight: -15
                        identifier: name
                      - code: established_accounts
                        weight: -15
                        identifier: email
                      - code: aged_identity
                        weight: -25
                        identifier: email
                  decisions_by_flow:
                    account_creation: allow
                    login: allow
                    purchase: allow
                  assessment_id: asm_01JA1Y7J5P3T6V8WABCDEFGHJK
                  updated_at: '2026-10-12T16:20:03.000Z'
                detail:
                  schema_version: '1'
                  assessment_id: asm_01JA2Z8K6Q4V7W9XBCDEFGHJKM
                  account_id: acct_7f3a9c
                  request_id: req-2026-10-14-0001
                  policy_version: heuristic-2026-10.1
                  policy_basis: heuristic_unvalidated
                  assessment_version: 2
                  created_at: '2026-10-14T09:00:00.000Z'
                  updated_at: '2026-10-14T09:00:00.412Z'
                  expires_at: '2027-10-14T09:00:00.000Z'
                  timing:
                    deadline_ms: 300
                    elapsed_ms: 301
                  status: pending
                  confidence: unavailable
                  incomplete_sources:
                    - lane: accounts
                      reason: timed_out
                    - lane: breach
                      reason: timed_out
                  assessment_url: /v1/assessments/asm_01JA2Z8K6Q4V7W9XBCDEFGHJKM
            login:
              value:
                schema_version: '1'
                id: asm_01JB3C4D5E6F7G8H9JKMNPQRST
                status: complete
                flow: login
                depth: quick
                account:
                  schema_version: '1'
                  id: acct_8412
                  risk:
                    score: 0
                    decision: allow
                    reasons:
                      - code: credential_list_exposure
                        weight: 10
                        identifier: email
                      - code: established_accounts
                        weight: -15
                      - code: aged_identity
                        weight: -25
                        identifier: email
                  decisions_by_flow:
                    account_creation: allow
                    login: allow
                    purchase: allow
                  assessment_id: asm_01JB3C4D5E6F7G8H9JKMNPQRST
                  updated_at: '2026-10-18T11:00:00.212Z'
                detail:
                  schema_version: '1'
                  assessment_id: asm_01JB3C4D5E6F7G8H9JKMNPQRST
                  account_id: acct_8412
                  request_id: req_01
                  status: complete
                  recommendation: allow
                  confidence: high
                  risk:
                    score: 0
                    band: low
                    recommendation: allow
                    block: false
                    confidence: high
                    policy_version: risk-2026-10.3
                    policy_basis: heuristic_unvalidated
                    reasons:
                      - code: credential_list_exposure
                        weight: 10
                        identifier: email
                      - code: established_accounts
                        weight: -15
                      - code: aged_identity
                        weight: -25
                        identifier: email
                    summary:
                      email:
                        disposable: false
                        accounts_found: 4
                        breach:
                          found: true
                          breach_count: 5
                          first_year: 2014
                          last_year: 2022
                          exposed:
                            - email
                            - name
                            - password_hash
                          in_credential_lists: true
                          recent_password_exposure: false
                          truncated: false
                    coverage:
                      answered: 6
                      failed: 0
                      pending: 0
                  incomplete_sources: []
                  policy_version: risk-2026-10.3
                  policy_basis: heuristic_unvalidated
                  assessment_version: 1
                  created_at: '2026-10-18T11:00:00.000Z'
                  updated_at: '2026-10-18T11:00:00.212Z'
                  expires_at: '2027-10-18T11:00:00.000Z'
                  timing:
                    deadline_ms: 500
                    elapsed_ms: 212
            detailed:
              value:
                schema_version: '1'
                id: asm_01JB3C4D5E6F7G8H9JKMNPQRST
                status: complete
                flow: account_creation
                depth: full
                account:
                  schema_version: '1'
                  id: acct_8412
                  risk:
                    score: 10
                    decision: allow
                    reasons:
                      - code: voip_number
                        weight: 25
                        identifier: phone
                      - code: breach_name_match
                        weight: -15
                        identifier: name
                  decisions_by_flow:
                    account_creation: allow
                    login: allow
                    purchase: allow
                  assessment_id: asm_01JB3C4D5E6F7G8H9JKMNPQRST
                  updated_at: '2026-10-18T11:00:04.000Z'
                detail:
                  schema_version: '1'
                  assessment_id: asm_01JB3C4D5E6F7G8H9JKMNPQRST
                  account_id: acct_8412
                  request_id: req_01
                  status: complete
                  recommendation: allow
                  confidence: high
                  risk:
                    score: 10
                    band: low
                    recommendation: allow
                    block: false
                    confidence: high
                    policy_version: risk-2026-10.3
                    policy_basis: heuristic_unvalidated
                    reasons:
                      - code: voip_number
                        weight: 25
                        identifier: phone
                      - code: breach_name_match
                        weight: -15
                        identifier: name
                    summary:
                      email:
                        disposable: false
                        accounts_found: 1
                        breach:
                          found: true
                          breach_count: 2
                          first_year: 2016
                          last_year: 2019
                          exposed:
                            - email
                            - password
                            - password_hash
                          in_credential_lists: true
                          truncated: false
                      phone:
                        line_type: voip
                        country: US
                      consistency:
                        name: match
                    coverage:
                      answered: 4
                      failed: 0
                      pending: 0
                    details:
                      phone_names:
                        - value: Jane Doe
                          seen_by: 3
                      breaches:
                        - name: 'Collection #1'
                          category: combolist
                          kind: credential_list
                          year: 2019
                          matched_on: email
                          exposed:
                            - email
                            - password
                        - name: LinkedIn
                          domain: linkedin.com
                          category: social
                          kind: site_breach
                          year: 2016
                          month: 5
                          matched_on: email
                          exposed:
                            - email
                            - password_hash
                      breach_names:
                        - value: Jane Doe
                          seen_in: 2
                  signals:
                    - type: account_presence
                      identifier: email
                      outcome: found
                      source_id: src_3f9a1c
                      evidence_ref: evr_01JB3C4D5E6F7G8H9JKMNPQRSV
                      observed_at: '2026-10-18T11:00:00.180Z'
                      last_checked_at: '2026-10-18T11:00:00.180Z'
                      freshness: fresh
                    - type: breach_exposure
                      identifier: email
                      outcome: found
                      source_id: src_8d27e4
                      evidence_ref: evr_01JB3C4D5E6F7G8H9JKMNPQRSW
                      observed_at: '2026-10-18T11:00:01.900Z'
                      last_checked_at: '2026-10-18T11:00:01.900Z'
                      freshness: fresh
                    - type: account_presence
                      identifier: phone
                      outcome: found
                      source_id: src_51b0d7
                      evidence_ref: evr_01JB3C4D5E6F7G8H9JKMNPQRSX
                      observed_at: '2026-10-18T11:00:03.700Z'
                      last_checked_at: '2026-10-18T11:00:03.700Z'
                      freshness: fresh
                  incomplete_sources: []
                  policy_version: risk-2026-10.3
                  policy_basis: heuristic_unvalidated
                  assessment_version: 2
                  created_at: '2026-10-18T11:00:00.000Z'
                  updated_at: '2026-10-18T11:00:04.000Z'
                  expires_at: '2027-10-18T11:00:00.000Z'
                  timing:
                    deadline_ms: 500
                    elapsed_ms: 4000
    InvalidQuery:
      description: >-
        A query parameter is unknown, repeated or outside its documented values,
        or the route takes no query parameters and one was sent. For a refused
        value invalid_params names the parameter; for an unknown or repeated
        parameter, or any parameter on a route that takes none, its field is
        query.
      headers:
        Cache-Control:
          schema:
            type: string
            const: no-store
          required: true
        X-Request-ID:
          description: The request correlation id, 32 lowercase hexadecimal characters.
          schema:
            type: string
            pattern: ^[0-9a-f]{32}$
            not:
              pattern: \n
          required: true
      content:
        application/problem+json:
          schema:
            allOf:
              - $ref: '#/components/schemas/Problem'
              - properties:
                  status:
                    const: 400
                  code:
                    enum:
                      - invalid_request
    Unauthorized:
      description: No API key, or one that is malformed, unknown, revoked or expired.
      headers:
        Cache-Control:
          schema:
            type: string
            const: no-store
          required: true
        WWW-Authenticate:
          schema:
            type: string
            const: Bearer realm="noresponse-assessments"
          required: true
        X-Request-ID:
          description: The request correlation id, 32 lowercase hexadecimal characters.
          schema:
            type: string
            pattern: ^[0-9a-f]{32}$
            not:
              pattern: \n
          required: true
      content:
        application/problem+json:
          schema:
            allOf:
              - $ref: '#/components/schemas/Problem'
              - properties:
                  status:
                    const: 401
                  code:
                    enum:
                      - unauthorized
    WorkspaceForbidden:
      description: >-
        The API key is valid but may not use this operation: it lacks the
        operation's scope, or its workspace is not entitled or is suspended.
      headers:
        Cache-Control:
          schema:
            type: string
            const: no-store
          required: true
        X-Request-ID:
          description: The request correlation id, 32 lowercase hexadecimal characters.
          schema:
            type: string
            pattern: ^[0-9a-f]{32}$
            not:
              pattern: \n
          required: true
      content:
        application/problem+json:
          schema:
            allOf:
              - $ref: '#/components/schemas/Problem'
              - properties:
                  status:
                    const: 403
                  code:
                    enum:
                      - workspace_forbidden
          examples:
            missingScope:
              value:
                type: https://docs.noresponse.org/problems/workspace-forbidden
                title: Forbidden
                status: 403
                detail: The API key does not carry a scope this operation accepts.
                code: workspace_forbidden
                request_id: 0123456789abcdef0123456789abcdef
    NotFound:
      description: >-
        No unexpired assessment with this id for the calling workspace, or a
        malformed assessment_id.
      headers:
        Cache-Control:
          schema:
            type: string
            const: no-store
          required: true
        X-Request-ID:
          description: The request correlation id, 32 lowercase hexadecimal characters.
          schema:
            type: string
            pattern: ^[0-9a-f]{32}$
            not:
              pattern: \n
          required: true
      content:
        application/problem+json:
          schema:
            allOf:
              - $ref: '#/components/schemas/Problem'
              - properties:
                  status:
                    const: 404
                  code:
                    enum:
                      - not_found
    RateLimited:
      description: >-
        The workspace's rate or concurrency limit is exhausted. Retry-After says
        when to retry; the provider applies its own fallback meanwhile.
      headers:
        Cache-Control:
          schema:
            type: string
            const: no-store
          required: true
        Retry-After:
          description: >-
            Whole seconds to wait before polling or retrying. Required on 202,
            429 and 503.
          schema:
            type: string
            pattern: >-
              ^(?:[1-9]|[1-9][0-9]|[1-9][0-9]{2}|[12][0-9]{3}|3[0-5][0-9]{2}|3600)$
            description: Whole decimal seconds; wait at least this long.
          required: true
        X-Request-ID:
          description: The request correlation id, 32 lowercase hexadecimal characters.
          schema:
            type: string
            pattern: ^[0-9a-f]{32}$
            not:
              pattern: \n
          required: true
      content:
        application/problem+json:
          schema:
            allOf:
              - $ref: '#/components/schemas/Problem'
              - properties:
                  status:
                    const: 429
                  code:
                    enum:
                      - rate_limited
          examples:
            limited:
              value:
                type: https://docs.noresponse.org/problems/rate-limited
                title: Rate limited
                status: 429
                detail: >-
                  The tenant's assessment rate is exhausted; retry after the
                  Retry-After interval.
                code: rate_limited
                request_id: 0123456789abcdef0123456789abcdef
    ServiceUnavailable:
      description: >-
        The assessment could not be admitted at all (overload, shutdown or a
        dependency down). An assessment that was admitted answers partial or
        pending instead of 503.
      headers:
        Cache-Control:
          schema:
            type: string
            const: no-store
          required: true
        Retry-After:
          description: >-
            Whole seconds to wait before polling or retrying. Required on 202,
            429 and 503.
          schema:
            type: string
            pattern: >-
              ^(?:[1-9]|[1-9][0-9]|[1-9][0-9]{2}|[12][0-9]{3}|3[0-5][0-9]{2}|3600)$
            description: Whole decimal seconds; wait at least this long.
          required: true
        X-Request-ID:
          description: The request correlation id, 32 lowercase hexadecimal characters.
          schema:
            type: string
            pattern: ^[0-9a-f]{32}$
            not:
              pattern: \n
          required: true
      content:
        application/problem+json:
          schema:
            allOf:
              - $ref: '#/components/schemas/Problem'
              - properties:
                  status:
                    const: 503
                  code:
                    enum:
                      - service_unavailable
  schemas:
    Assessment:
      title: Assessment
      description: >-
        The assessment resource: the body of POST /v1/assessments (200 complete
        or partial, 202 pending), GET /v1/assessments/{assessment_id} and the
        assessment.updated webhook. Its main object is account: the account's
        one current risk, as GET /v1/accounts/{account_id} serves it, with
        risk.decision the decision for this assessment's flow. detail holds this
        assessment's own facts and score. The account's current risk comes from
        its latest assessment that has a decision, which is this one once it has
        a decision and no newer one does, and an earlier one while this one is
        pending. Concurrent assessments of one account each answer the account's
        risk as committed when they are served.
      type: object
      additionalProperties: false
      required:
        - schema_version
        - id
        - status
        - flow
        - depth
        - detail
      properties:
        schema_version:
          const: '1'
          description: Version of the body shape.
        id:
          type: string
          pattern: ^asm_[0-9A-HJKMNP-TV-Z]{26}$
          description: This assessment's id, equal to detail.assessment_id.
          not:
            description: >-
              A line feed anywhere, refused with `not` beside every anchored
              pattern.
            pattern: \n
        status:
          enum:
            - complete
            - partial
            - pending
          description: >-
            This assessment's status, equal to detail.status. While it is
            pending, account carries the risk of the account's previous decided
            assessment, or is absent.
        flow:
          enum:
            - account_creation
            - login
            - purchase
          description: >-
            The flow the request named. account.risk.decision is the decision
            for it. An assessment made before flows existed reports
            account_creation.
        depth:
          enum:
            - quick
            - full
          description: >-
            The depth the assessment was served at: the request's, or its flow's
            default. An assessment made before depths existed reports full.
        account:
          title: Account
          description: >-
            The account's one current risk when this assessment was served,
            decided for this assessment's flow: the body GET
            /v1/accounts/{account_id} would answer, with risk.decision equal to
            decisions_by_flow for flow. Absent only while the account has no
            assessment with a decision (its first assessment is still pending);
            a webhook or GET of the decided assessment then carries it.
          type: object
          additionalProperties: false
          required:
            - schema_version
            - id
            - risk
            - decisions_by_flow
            - assessment_id
            - updated_at
          properties:
            schema_version:
              const: '1'
              description: Version of the body shape.
            id:
              type: string
              minLength: 1
              maxLength: 128
              pattern: ^[A-Za-z0-9][A-Za-z0-9._:|-]{0,127}$
              description: The account_id the workspace sends with its assessments.
              not:
                description: refused_text plus secret_encoded, for account_id.
                anyOf:
                  - description: >-
                      A line feed anywhere, refused with `not` beside every
                      anchored pattern.
                    pattern: \n
                  - description: >-
                      Exact shapes only: a complete modular-crypt password hash
                      (bcrypt $2a$/$2b$/$2x$/$2y$ with a two-digit cost and 53
                      characters; $argon2i/d/id with its m, t, p parameters,
                      salt and hash; md5-crypt $1$, sha256-crypt $5$ or
                      sha512-crypt $6$ with a 22, 43 or 86 character hash;
                      passlib $scrypt$ with ln, r, p, salt and hash) or a
                      three-segment JWT whose header is base64url JSON opening
                      with an "alg", "typ", "kid" or "cty" member (eyJhbGciOi,
                      eyJ0eXAiOi, eyJraWQiOi or eyJjdHkiOi). A value that merely
                      starts with '$2' or 'eyJ', such as eyJohnathan.doe.x, is
                      not refused. Best effort, not a guarantee; see the
                      provider obligation in the README.
                    anyOf:
                      - pattern: ^\$2[abxy]?\$[0-9]{2}\$[./A-Za-z0-9]{53}$
                      - pattern: >-
                          ^\$argon2(?:id|i|d)\$(?:v=[0-9]{1,4}\$)?m=[0-9]{1,10},t=[0-9]{1,10},p=[0-9]{1,3}\$[A-Za-z0-9+/]{8,}\$[A-Za-z0-9+/]{16,}$
                      - pattern: >-
                          ^\$[156]\$(?:rounds=[0-9]{1,9}\$)?[./A-Za-z0-9]{1,16}\$(?:[./A-Za-z0-9]{22}|[./A-Za-z0-9]{43}|[./A-Za-z0-9]{86})$
                      - pattern: >-
                          ^\$scrypt\$ln=[0-9]{1,2},r=[0-9]{1,3},p=[0-9]{1,3}\$[A-Za-z0-9+/.]{8,}\$[A-Za-z0-9+/.]{16,}$
                      - pattern: >-
                          ^eyJ(?:hbGciOi|0eXAiOi|raWQiOi|jdHkiOi)[A-Za-z0-9_-]*\.[A-Za-z0-9_-]{2,}\.[A-Za-z0-9_-]*$
            risk:
              type: object
              additionalProperties: false
              required:
                - score
                - decision
                - reasons
              properties:
                score:
                  type: integer
                  minimum: 0
                  maximum: 100
                  description: 0 (safe) to 100 (risky), as risk.score of the assessment.
                decision:
                  enum:
                    - allow
                    - step_up
                    - review
                    - block
                  description: >-
                    The decision for the flow of the assessment this account is
                    served with: on GET /v1/accounts/{account_id}, the flow of
                    the current assessment; inside an assessment, that
                    assessment's flow.
                reasons:
                  type: array
                  maxItems: 32
                  description: >-
                    Every reason that fired, highest weight first. The weights
                    sum to score before clamping.
                  items:
                    type: object
                    additionalProperties: false
                    required:
                      - code
                      - weight
                    properties:
                      code:
                        enum:
                          - no_digital_footprint
                          - voip_number
                          - disposable_email
                          - new_email
                          - spam_reports
                          - fraud_flag
                          - identity_mismatch
                          - country_mismatch
                          - proxy_ip
                          - seen_before
                          - shared_ip
                          - many_recent_accounts
                          - established_accounts
                          - aged_identity
                          - breach_name_match
                          - breach_cooccurrence
                          - breach_name_mismatch
                          - breach_phone_mismatch
                          - recent_password_exposure
                          - credential_list_exposure
                          - abuse_ecosystem_member
                          - no_breach_history
                          - automation_fast_submit
                          - client_clock_skew
                          - bot_or_automation
                          - auth_email_verified
                          - auth_phone_verified
                          - auth_mfa_recent
                          - auth_new_session
                          - auth_new_account
                          - auth_impersonated
                          - context_timezone_mismatch
                          - context_locale_mismatch
                          - context_line_country_mismatch
                          - prior_abuse_link
                          - test_scenario
                          - shared_api_key
                        description: >-
                          A risk reason from the reviewed list.
                          old_breach_history and consistent_identity were
                          replaced by the breach codes (aged_identity,
                          breach_name_match, breach_cooccurrence and the
                          mismatches) and are refused. test_scenario appears
                          only on an assessment made with a test key
                          (nrk_test_), which the deterministic simulator
                          answers: its weight is the scenario the magic email or
                          phone chose, and 0 for any other identifier. A live
                          assessment never carries it. shared_api_key is an
                          account reason, never an assessment one: it appears
                          only in the risk of GET /v1/accounts/{account_id} and
                          the account an assessment carries, when a key your
                          account creation gate issued to the account
                          (issued_credential.sha256) was used from many IP
                          addresses or countries within 24 hours (POST
                          /v1/key_usage/batches).
                      weight:
                        type: integer
                        minimum: -100
                        maximum: 100
                      identifier:
                        enum:
                          - email
                          - username
                          - phone
                          - name
                          - ip
                          - context
                        description: >-
                          The submitted identifier or bounded client context a
                          reason concerns; absent when it concerns the whole
                          assessment. Context is a claimed, untrusted hint and
                          never a device fingerprint.
            decisions_by_flow:
              type: object
              additionalProperties: false
              required:
                - account_creation
                - login
                - purchase
              description: >-
                The decision for each flow: the account's score under that
                flow's thresholds. A flow the workspace has not set uses its
                account_creation thresholds, so the flows differ only where it
                set them.
              properties:
                account_creation:
                  enum:
                    - allow
                    - step_up
                    - review
                    - block
                  description: >-
                    block when the score reached the workspace's block threshold
                    (risk.block of the assessment), otherwise the assessment's
                    recommendation. Advisory: the workspace decides and
                    enforces.
                login:
                  enum:
                    - allow
                    - step_up
                    - review
                    - block
                  description: >-
                    block when the score reached the workspace's block threshold
                    (risk.block of the assessment), otherwise the assessment's
                    recommendation. Advisory: the workspace decides and
                    enforces.
                purchase:
                  enum:
                    - allow
                    - step_up
                    - review
                    - block
                  description: >-
                    block when the score reached the workspace's block threshold
                    (risk.block of the assessment), otherwise the assessment's
                    recommendation. Advisory: the workspace decides and
                    enforces.
            assessment_id:
              type: string
              pattern: ^asm_[0-9A-HJKMNP-TV-Z]{26}$
              description: The assessment the current risk comes from.
              not:
                description: >-
                  A line feed anywhere, refused with `not` beside every anchored
                  pattern.
                pattern: \n
            updated_at:
              type: string
              format: date-time
              description: updated_at of that assessment's latest revision.
          $defs:
            account_decision:
              enum:
                - allow
                - step_up
                - review
                - block
              description: >-
                block when the score reached the workspace's block threshold
                (risk.block of the assessment), otherwise the assessment's
                recommendation. Advisory: the workspace decides and enforces.
        detail:
          title: Assessment detail
          description: >-
            This assessment's own facts: its score, recommendation, signals,
            coverage and timing.
          type: object
          additionalProperties: false
          required:
            - schema_version
            - assessment_id
            - account_id
            - status
            - confidence
            - incomplete_sources
            - policy_version
            - policy_basis
            - assessment_version
            - created_at
            - updated_at
            - expires_at
            - timing
          properties:
            schema_version:
              const: '1'
              description: Version of the body shape.
            assessment_id:
              type: string
              pattern: ^asm_[0-9A-HJKMNP-TV-Z]{26}$
              description: >-
                Opaque, server-assigned assessment id: 'asm_' and a 26-character
                Crockford base32 ULID. Unique within the workspace; another
                workspace's assessment id answers 404.
              not:
                description: >-
                  A line feed anywhere, refused with `not` beside every anchored
                  pattern.
                pattern: \n
            account_id:
              type: string
              minLength: 1
              maxLength: 128
              pattern: ^[A-Za-z0-9][A-Za-z0-9._:|-]{0,127}$
              description: >-
                The provider's own opaque identifier for the account being
                checked, scoped to the calling workspace. It must be
                provider-opaque and must not contain a direct identifier (email,
                phone, name, national id): that is a provider obligation the
                schema can only partly check. '|' is accepted so an Auth0 user
                id such as 'auth0|64abc' passes unchanged; '@', '+', '$' and
                whitespace are refused by the pattern, as is an exact-shape JWT;
                a hex digest such as a SHA-256 is allowed, because hashing an
                internal id is a common pseudonymous scheme. A value such as
                '07700900123' or 'jane.doe.gmail.com' cannot be told apart from
                an opaque id. It travels in bodies, and in a URL only as the
                path segment of GET /v1/accounts/{account_id} and its
                /assessments. An assessment requested by a provider hook at
                pre_registration, which has no account yet, carries the
                server-issued account_id pre: followed by its assessment_id.
              not:
                description: refused_text plus secret_encoded, for account_id.
                anyOf:
                  - description: >-
                      A line feed anywhere, refused with `not` beside every
                      anchored pattern.
                    pattern: \n
                  - description: >-
                      Exact shapes only: a complete modular-crypt password hash
                      (bcrypt $2a$/$2b$/$2x$/$2y$ with a two-digit cost and 53
                      characters; $argon2i/d/id with its m, t, p parameters,
                      salt and hash; md5-crypt $1$, sha256-crypt $5$ or
                      sha512-crypt $6$ with a 22, 43 or 86 character hash;
                      passlib $scrypt$ with ln, r, p, salt and hash) or a
                      three-segment JWT whose header is base64url JSON opening
                      with an "alg", "typ", "kid" or "cty" member (eyJhbGciOi,
                      eyJ0eXAiOi, eyJraWQiOi or eyJjdHkiOi). A value that merely
                      starts with '$2' or 'eyJ', such as eyJohnathan.doe.x, is
                      not refused. Best effort, not a guarantee; see the
                      provider obligation in the README.
                    anyOf:
                      - pattern: ^\$2[abxy]?\$[0-9]{2}\$[./A-Za-z0-9]{53}$
                      - pattern: >-
                          ^\$argon2(?:id|i|d)\$(?:v=[0-9]{1,4}\$)?m=[0-9]{1,10},t=[0-9]{1,10},p=[0-9]{1,3}\$[A-Za-z0-9+/]{8,}\$[A-Za-z0-9+/]{16,}$
                      - pattern: >-
                          ^\$[156]\$(?:rounds=[0-9]{1,9}\$)?[./A-Za-z0-9]{1,16}\$(?:[./A-Za-z0-9]{22}|[./A-Za-z0-9]{43}|[./A-Za-z0-9]{86})$
                      - pattern: >-
                          ^\$scrypt\$ln=[0-9]{1,2},r=[0-9]{1,3},p=[0-9]{1,3}\$[A-Za-z0-9+/.]{8,}\$[A-Za-z0-9+/.]{16,}$
                      - pattern: >-
                          ^eyJ(?:hbGciOi|0eXAiOi|raWQiOi|jdHkiOi)[A-Za-z0-9_-]*\.[A-Za-z0-9_-]{2,}\.[A-Za-z0-9_-]*$
            request_id:
              type: string
              minLength: 1
              maxLength: 128
              pattern: ^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$
              description: >-
                An optional provider correlation id, echoed back. It is not an
                idempotency key. Refuses an exact-shape JWT or a bare 40, 64 or
                128 character hex digest; a UUID is accepted.
              not:
                description: >-
                  refused_text plus secret_hex_digest and secret_encoded, for
                  request_id and username.
                anyOf:
                  - description: >-
                      A line feed anywhere, refused with `not` beside every
                      anchored pattern.
                    pattern: \n
                  - description: >-
                      Exactly 40, 64 or 128 hex characters (SHA-1, SHA-256,
                      SHA-512) and nothing else. Refused in username and
                      request_id, where such a value is almost certainly a
                      credential hash; a 39 or 41 character hex string, a short
                      hex word such as 'deadbeef' or a UUID is accepted. Not
                      refused in account_id: a hex digest of an internal id is a
                      common pseudonymous account id and not a secret under.
                    pattern: ^(?:[0-9A-Fa-f]{40}|[0-9A-Fa-f]{64}|[0-9A-Fa-f]{128})$
                  - description: >-
                      Exact shapes only: a complete modular-crypt password hash
                      (bcrypt $2a$/$2b$/$2x$/$2y$ with a two-digit cost and 53
                      characters; $argon2i/d/id with its m, t, p parameters,
                      salt and hash; md5-crypt $1$, sha256-crypt $5$ or
                      sha512-crypt $6$ with a 22, 43 or 86 character hash;
                      passlib $scrypt$ with ln, r, p, salt and hash) or a
                      three-segment JWT whose header is base64url JSON opening
                      with an "alg", "typ", "kid" or "cty" member (eyJhbGciOi,
                      eyJ0eXAiOi, eyJraWQiOi or eyJjdHkiOi). A value that merely
                      starts with '$2' or 'eyJ', such as eyJohnathan.doe.x, is
                      not refused. Best effort, not a guarantee; see the
                      provider obligation in the README.
                    anyOf:
                      - pattern: ^\$2[abxy]?\$[0-9]{2}\$[./A-Za-z0-9]{53}$
                      - pattern: >-
                          ^\$argon2(?:id|i|d)\$(?:v=[0-9]{1,4}\$)?m=[0-9]{1,10},t=[0-9]{1,10},p=[0-9]{1,3}\$[A-Za-z0-9+/]{8,}\$[A-Za-z0-9+/]{16,}$
                      - pattern: >-
                          ^\$[156]\$(?:rounds=[0-9]{1,9}\$)?[./A-Za-z0-9]{1,16}\$(?:[./A-Za-z0-9]{22}|[./A-Za-z0-9]{43}|[./A-Za-z0-9]{86})$
                      - pattern: >-
                          ^\$scrypt\$ln=[0-9]{1,2},r=[0-9]{1,3},p=[0-9]{1,3}\$[A-Za-z0-9+/.]{8,}\$[A-Za-z0-9+/.]{16,}$
                      - pattern: >-
                          ^eyJ(?:hbGciOi|0eXAiOi|raWQiOi|jdHkiOi)[A-Za-z0-9_-]*\.[A-Za-z0-9_-]{2,}\.[A-Za-z0-9_-]*$
            status:
              enum:
                - complete
                - partial
                - pending
              description: >-
                complete: final; nothing is still running. A lane that failed or
                missed its 10 s deadline stays listed in incomplete_sources, and
                confidence is lower. partial: a recommendation exists and at
                least one lane is still running or did not settle (see
                incomplete_sources). pending: nothing usable before the
                deadline; no recommendation yet, poll or wait for the webhook.
            recommendation:
              enum:
                - allow
                - step_up
                - review
              description: Advisory only. The provider decides and enforces.
            confidence:
              enum:
                - low
                - medium
                - high
                - unavailable
              description: >-
                Ordinal confidence in the recommendation under the current
                heuristic policy. It is not a probability.
            risk:
              type: object
              additionalProperties: false
              required:
                - score
                - band
                - recommendation
                - confidence
                - policy_version
                - policy_basis
                - reasons
                - coverage
              description: >-
                the one risk decision for this assessment. score is 0 (safe) to
                100 (risky): the sum of the weights of the reasons that fired,
                clamped to 0..100, from hand-set versioned weights. Every served
                answer with a recommendation carries it, and there the top-level
                recommendation equals risk.recommendation. block is true from
                the workspace's block threshold (block_threshold), off by
                default. It names no source or provider.
              properties:
                score:
                  type: integer
                  minimum: 0
                  maximum: 100
                band:
                  enum:
                    - low
                    - medium
                    - high
                    - critical
                  description: low 0-29, medium 30-59, high 60-84, critical 85-100.
                recommendation:
                  enum:
                    - allow
                    - step_up
                    - review
                  description: Advisory only. The provider decides and enforces.
                block:
                  type: boolean
                  description: >-
                    true when the workspace's block threshold is set and score
                    reached it. A provider hook can deny the account creation on
                    it; the provider decides and enforces. It does not change
                    recommendation. It is false while blocking is off, the
                    default, and a body from before the flag existed omits it:
                    read absent as false.
                block_threshold:
                  type: integer
                  minimum: 1
                  maximum: 100
                  description: >-
                    The block threshold this answer used: block is true exactly
                    when score is at least this value. Absent while blocking is
                    off. NoResponse sets it per workspace on request, at or
                    above the review threshold.
                confidence:
                  enum:
                    - low
                    - medium
                    - high
                  description: >-
                    How much of the planned evidence answered; it says nothing
                    about risk.
                policy_version:
                  type: string
                  minLength: 1
                  maxLength: 64
                  pattern: ^[a-z0-9][a-z0-9._-]{0,63}(\+t[1-9][0-9]{0,8})?$
                  description: >-
                    Version of the hand-authored heuristic weights that produced
                    the recommendation, for example 'risk-2026-10.7'. A
                    workspace threshold override adds a +t<N> suffix, e.g.
                    'risk-2026-10.7+t3'.
                  not:
                    description: >-
                      A line feed anywhere, refused with `not` beside every
                      anchored pattern.
                    pattern: \n
                policy_basis:
                  const: heuristic_unvalidated
                reasons:
                  type: array
                  maxItems: 32
                  description: >-
                    Every reason that fired, highest weight first. The weights
                    sum to score before clamping.
                  items:
                    type: object
                    additionalProperties: false
                    required:
                      - code
                      - weight
                    properties:
                      code:
                        enum:
                          - no_digital_footprint
                          - voip_number
                          - disposable_email
                          - new_email
                          - spam_reports
                          - fraud_flag
                          - identity_mismatch
                          - country_mismatch
                          - proxy_ip
                          - seen_before
                          - shared_ip
                          - many_recent_accounts
                          - established_accounts
                          - aged_identity
                          - breach_name_match
                          - breach_cooccurrence
                          - breach_name_mismatch
                          - breach_phone_mismatch
                          - recent_password_exposure
                          - credential_list_exposure
                          - abuse_ecosystem_member
                          - no_breach_history
                          - automation_fast_submit
                          - client_clock_skew
                          - bot_or_automation
                          - auth_email_verified
                          - auth_phone_verified
                          - auth_mfa_recent
                          - auth_new_session
                          - auth_new_account
                          - auth_impersonated
                          - context_timezone_mismatch
                          - context_locale_mismatch
                          - context_line_country_mismatch
                          - prior_abuse_link
                          - test_scenario
                          - shared_api_key
                        description: >-
                          A risk reason from the reviewed list.
                          old_breach_history and consistent_identity were
                          replaced by the breach codes (aged_identity,
                          breach_name_match, breach_cooccurrence and the
                          mismatches) and are refused. test_scenario appears
                          only on an assessment made with a test key
                          (nrk_test_), which the deterministic simulator
                          answers: its weight is the scenario the magic email or
                          phone chose, and 0 for any other identifier. A live
                          assessment never carries it. shared_api_key is an
                          account reason, never an assessment one: it appears
                          only in the risk of GET /v1/accounts/{account_id} and
                          the account an assessment carries, when a key your
                          account creation gate issued to the account
                          (issued_credential.sha256) was used from many IP
                          addresses or countries within 24 hours (POST
                          /v1/key_usage/batches).
                      weight:
                        type: integer
                        minimum: -100
                        maximum: 100
                      identifier:
                        enum:
                          - email
                          - username
                          - phone
                          - name
                          - ip
                          - context
                        description: >-
                          The submitted identifier or bounded client context a
                          reason concerns; absent when it concerns the whole
                          assessment. Context is a claimed, untrusted hint and
                          never a device fingerprint.
                summary:
                  type: object
                  additionalProperties: false
                  properties:
                    phone:
                      type: object
                      additionalProperties: false
                      properties:
                        line_type:
                          enum:
                            - mobile
                            - voip
                            - landline
                            - toll_free
                            - other
                        country:
                          type: string
                          pattern: ^[A-Z]{2}$
                          not:
                            pattern: \n
                        report_count:
                          type: integer
                          minimum: 0
                          description: Highest report count any source gave for the number.
                        carrier:
                          type: string
                          minLength: 1
                          maxLength: 128
                          description: >-
                            Carrier-network metadata from privately weighted
                            sources; not upstream provider attribution.
                    email:
                      type: object
                      additionalProperties: false
                      properties:
                        disposable:
                          type: boolean
                        accounts_found:
                          type: integer
                          minimum: 0
                          description: Accounts found for the email.
                        breach:
                          type: object
                          additionalProperties: false
                          required:
                            - found
                          description: >-
                            Breach facts for the email. Replaces the boolean
                            breached.
                          properties:
                            found:
                              type: boolean
                            breach_count:
                              type: integer
                              minimum: 0
                              description: Distinct breach tables the value appears in.
                            first_year:
                              type: integer
                              minimum: 1970
                              maximum: 2100
                              description: Year of the oldest dated table.
                            last_year:
                              type: integer
                              minimum: 1970
                              maximum: 2100
                              description: Year of the newest dated table.
                            exposed:
                              type: array
                              maxItems: 11
                              items:
                                enum:
                                  - email
                                  - username
                                  - name
                                  - password
                                  - password_hash
                                  - phone
                                  - address
                                  - dob
                                  - ip
                                  - payment
                                  - security_qa
                                description: >-
                                  A kind of data a breach table held next to the
                                  identifier. password means a plaintext
                                  password was present; NoResponse never stores
                                  it and never says what it was. password_hash
                                  means a hash, salt or token was present. A
                                  value, never: the schema has no member for
                                  one.
                              description: >-
                                The union of data kinds the matching tables
                                held, never the values.
                            in_credential_lists:
                              type: boolean
                              description: >-
                                The value is in a credential_list or stealer_log
                                table.
                            recent_password_exposure:
                              type: boolean
                              description: >-
                                A plaintext password sat next to the value in a
                                table dated two years ago or less, or the value
                                is in a stealer_log table.
                            truncated:
                              type: boolean
                          allOf:
                            - if:
                                properties:
                                  truncated:
                                    const: true
                                required:
                                  - truncated
                              then:
                                properties:
                                  found:
                                    const: true
                            - if:
                                properties:
                                  found:
                                    const: false
                                required:
                                  - found
                              then:
                                not:
                                  anyOf:
                                    - required:
                                        - first_year
                                    - required:
                                        - last_year
                                    - required:
                                        - exposed
                    username:
                      type: object
                      additionalProperties: false
                      properties:
                        accounts_found:
                          type: integer
                          minimum: 0
                          description: Accounts found for the username.
                        breach:
                          type: object
                          additionalProperties: false
                          required:
                            - found
                          description: Breach facts for the username.
                          properties:
                            found:
                              type: boolean
                            breach_count:
                              type: integer
                              minimum: 0
                              description: Distinct breach tables the value appears in.
                            first_year:
                              type: integer
                              minimum: 1970
                              maximum: 2100
                              description: Year of the oldest dated table.
                            last_year:
                              type: integer
                              minimum: 1970
                              maximum: 2100
                              description: Year of the newest dated table.
                            exposed:
                              type: array
                              maxItems: 11
                              items:
                                enum:
                                  - email
                                  - username
                                  - name
                                  - password
                                  - password_hash
                                  - phone
                                  - address
                                  - dob
                                  - ip
                                  - payment
                                  - security_qa
                                description: >-
                                  A kind of data a breach table held next to the
                                  identifier. password means a plaintext
                                  password was present; NoResponse never stores
                                  it and never says what it was. password_hash
                                  means a hash, salt or token was present. A
                                  value, never: the schema has no member for
                                  one.
                              description: >-
                                The union of data kinds the matching tables
                                held, never the values.
                            in_credential_lists:
                              type: boolean
                              description: >-
                                The value is in a credential_list or stealer_log
                                table.
                            recent_password_exposure:
                              type: boolean
                              description: >-
                                A plaintext password sat next to the value in a
                                table dated two years ago or less, or the value
                                is in a stealer_log table.
                            truncated:
                              type: boolean
                          allOf:
                            - if:
                                properties:
                                  truncated:
                                    const: true
                                required:
                                  - truncated
                              then:
                                properties:
                                  found:
                                    const: true
                            - if:
                                properties:
                                  found:
                                    const: false
                                required:
                                  - found
                              then:
                                not:
                                  anyOf:
                                    - required:
                                        - first_year
                                    - required:
                                        - last_year
                                    - required:
                                        - exposed
                    ip:
                      type: object
                      additionalProperties: false
                      description: >-
                        Facts about the submitted IP from the offline database
                        and this workspace's own recent assessments. Every
                        member is optional; absent makes no claim.
                      properties:
                        country:
                          type: string
                          pattern: ^[A-Z]{2}$
                          not:
                            description: >-
                              A line feed anywhere, refused with `not` beside
                              every anchored pattern.
                            pattern: \n
                          description: ISO 3166-1 alpha-2 country of the address.
                        type:
                          enum:
                            - residential
                            - hosting
                            - vpn
                            - proxy
                            - tor
                            - mobile
                            - unknown
                          description: The address's network type.
                        seen_in_workspace:
                          type: integer
                          minimum: 0
                          description: >-
                            Assessments in this workspace with the same IP in
                            the last 24 hours, this one included. A count only.
                    consistency:
                      type: object
                      additionalProperties: false
                      description: >-
                        Cross-identifier agreement, computed from facts only.
                        Every member is optional; absent makes no claim.
                      properties:
                        name:
                          enum:
                            - match
                            - partial
                            - mismatch
                            - unknown
                          description: >-
                            The submitted name against breach names and
                            caller-ID names.
                        phone:
                          enum:
                            - match
                            - partial
                            - mismatch
                            - unknown
                          description: >-
                            The submitted phone against numbers found next to
                            the email in breach records.
                        ip:
                          enum:
                            - match
                            - partial
                            - mismatch
                            - unknown
                          description: >-
                            The submitted IP against IPs found next to the email
                            or username in breach records.
                        country:
                          enum:
                            - consistent
                            - mismatch
                            - unknown
                          description: >-
                            IP country, phone country, breach countries and
                            policy_context.region together.
                  description: >-
                    A few typed facts per identifier. Every fact is optional:
                    absent means the evidence did not answer and makes no claim,
                    while false or 0 is a definite answer. Lanes that do not
                    exist yet leave their members absent.
                coverage:
                  type: object
                  additionalProperties: false
                  required:
                    - answered
                    - failed
                    - pending
                  description: Sources by state, never by name.
                  properties:
                    answered:
                      type: integer
                      minimum: 0
                      description: Sources that gave a definite answer.
                    failed:
                      type: integer
                      minimum: 0
                      description: Sources that could not answer.
                    pending:
                      type: integer
                      minimum: 0
                      description: Sources still being asked.
                details:
                  type: object
                  additionalProperties: false
                  description: >-
                    Detailed view only (response_mode=detailed, which needs the
                    detailed scope); a standard answer never carries it. Merged
                    observations: no provider, source, origin, raw breach
                    record, value or score.
                  properties:
                    phone_names:
                      type: array
                      maxItems: 32
                      items:
                        type: object
                        additionalProperties: false
                        required:
                          - value
                          - seen_by
                        properties:
                          value:
                            type: string
                            minLength: 1
                            maxLength: 128
                          seen_by:
                            type: integer
                            minimum: 1
                    breaches:
                      type: array
                      maxItems: 50
                      items:
                        type: object
                        additionalProperties: false
                        required:
                          - name
                          - kind
                          - matched_on
                        description: >-
                          One breach table that matched, detailed view only. No
                          member carries a record, value, password or hash.
                        properties:
                          name:
                            type: string
                            minLength: 1
                            maxLength: 128
                            not:
                              description: >-
                                A line feed anywhere, refused with `not` beside
                                every anchored pattern.
                              pattern: \n
                          domain:
                            type: string
                            minLength: 3
                            maxLength: 253
                            pattern: >-
                              ^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,63}$
                            not:
                              description: >-
                                A line feed anywhere, refused with `not` beside
                                every anchored pattern.
                              pattern: \n
                            description: >-
                              The breached site's domain, lower case. Absent
                              when the table has none (a credential list, for
                              example).
                          category:
                            type: string
                            pattern: ^[a-z0-9_]{1,64}$
                            not:
                              description: >-
                                A line feed anywhere, refused with `not` beside
                                every anchored pattern.
                              pattern: \n
                            description: >-
                              The table's category from its name, lower case
                              (social, gaming, combolist...).
                          kind:
                            enum:
                              - site_breach
                              - credential_list
                              - stealer_log
                              - scrape
                              - hacking_forum
                              - abuse_service
                              - darkweb_site
                            description: >-
                              Who is in the table: site_breach, a site's own
                              users; credential_list, a combolist or
                              compilation; stealer_log, malware or botnet
                              victims; scrape; hacking_forum, a criminal
                              hacking, cracking or carding community;
                              abuse_service, the customers of DDoS-for-hire,
                              account generators, dump or card shops, darknet
                              markets, stalkerware or breach-lookup services;
                              darkweb_site, an onion site of unknown purpose.
                          year:
                            type: integer
                            minimum: 1970
                            maximum: 2100
                            description: A breach table's date year.
                          month:
                            type: integer
                            minimum: 1
                            maximum: 12
                            description: Absent when only the year is known.
                          matched_on:
                            enum:
                              - email
                              - username
                              - ip
                            description: >-
                              The submitted identifier a breach table matched
                              on. The phone is never a breach selector, and the
                              name is never looked up.
                          exposed:
                            type: array
                            maxItems: 11
                            items:
                              enum:
                                - email
                                - username
                                - name
                                - password
                                - password_hash
                                - phone
                                - address
                                - dob
                                - ip
                                - payment
                                - security_qa
                              description: >-
                                A kind of data a breach table held next to the
                                identifier. password means a plaintext password
                                was present; NoResponse never stores it and
                                never says what it was. password_hash means a
                                hash, salt or token was present. A value, never:
                                the schema has no member for one.
                      description: The matching breach tables, newest first, at most 50.
                    breach_names:
                      type: array
                      maxItems: 32
                      description: >-
                        Names found next to the identifiers in breach records,
                        merged, with the number of distinct tables each was seen
                        in.
                      items:
                        type: object
                        additionalProperties: false
                        required:
                          - value
                          - seen_in
                        properties:
                          value:
                            type: string
                            minLength: 1
                            maxLength: 128
                          seen_in:
                            type: integer
                            minimum: 1
              allOf:
                - if:
                    properties:
                      block:
                        const: true
                    required:
                      - block
                  then:
                    required:
                      - block_threshold
            signals:
              type: array
              maxItems: 256
              items:
                type: object
                additionalProperties: false
                required:
                  - type
                  - identifier
                  - outcome
                  - source_id
                  - freshness
                properties:
                  type:
                    type: string
                    minLength: 1
                    maxLength: 64
                    pattern: ^[a-z][a-z0-9_]{0,63}$
                    description: >-
                      The producer emits only registered, active types with a
                      registered identifier kind and outcome.
                    not:
                      description: >-
                        A line feed anywhere, refused with `not` beside every
                        anchored pattern.
                      pattern: \n
                  identifier:
                    enum:
                      - email
                      - username
                      - phone
                      - ip
                    description: >-
                      Which submitted identifier a signal concerns. ip is a
                      selector of breach_exposure only.
                  outcome:
                    enum:
                      - found
                      - not_found
                      - inconclusive
                      - blocked
                      - unavailable
                    description: >-
                      Per-signal outcome. A failure is never not_found: a source
                      that timed out, was blocked or errored reports blocked,
                      unavailable or inconclusive with a reason, and is listed
                      in incomplete_sources.
                  source_id:
                    type: string
                    minLength: 1
                    maxLength: 64
                    pattern: ^[a-z0-9][a-z0-9_.-]{0,63}$
                    description: >-
                      Opaque, workspace-scoped projection of the source that
                      produced a signal. It remains stable for this workspace
                      while the projection key is unchanged, but never
                      identifies an upstream provider, feed, breach table or
                      source record.
                    not:
                      description: >-
                        A line feed anywhere, refused with `not` beside every
                        anchored pattern.
                      pattern: \n
                  reason:
                    enum:
                      - timed_out
                      - rate_limited
                      - blocked
                      - source_error
                      - unavailable
                      - deferred
                      - insufficient_evidence
                    description: >-
                      Why a signal or source did not produce a definite
                      found/not_found. timed_out means the source missed the
                      request deadline; a continuation may still settle it.
                      deferred means the (source, identifier) pair is async-only
                      and was not attempted on the synchronous path; a
                      continuation settles it.
                  evidence_ref:
                    type: string
                    pattern: ^evr_[0-9A-HJKMNP-TV-Z]{26}$
                    description: >-
                      Opaque pointer to evidence NoResponse holds for this
                      signal. It never encodes the evidence itself (no breach
                      value, credential or page body).
                    not:
                      description: >-
                        A line feed anywhere, refused with `not` beside every
                        anchored pattern.
                      pattern: \n
                  observed_at:
                    type: string
                    format: date-time
                    description: When the evidence was first observed.
                  last_checked_at:
                    type: string
                    format: date-time
                    description: When the source was last queried for this identifier.
                  freshness:
                    enum:
                      - fresh
                      - stale
                      - unknown
                    description: >-
                      Freshness class of the evidence behind a signal. unknown
                      whenever no evidence was obtained.
                  enrichment:
                    type: object
                    additionalProperties: false
                    required:
                      - fields
                    properties:
                      fields:
                        type: object
                        minProperties: 1
                        additionalProperties: false
                        properties:
                          phone:
                            type: string
                            maxLength: 8192
                          name:
                            type: string
                            maxLength: 8192
                          carrier:
                            type: string
                            maxLength: 8192
                          line_type:
                            type: string
                            maxLength: 8192
                          entity_type:
                            type: string
                            maxLength: 8192
                          country_code:
                            type: string
                            maxLength: 8192
                          country:
                            type: string
                            maxLength: 8192
                          state:
                            type: string
                            maxLength: 8192
                          city:
                            type: string
                            maxLength: 8192
                          location:
                            type: string
                            maxLength: 8192
                          national_format:
                            type: string
                            maxLength: 8192
                          job_title:
                            type: string
                            maxLength: 8192
                          company_name:
                            type: string
                            maxLength: 8192
                          email:
                            type: string
                            maxLength: 8192
                          website:
                            type: string
                            maxLength: 8192
                          first_call_at:
                            type: string
                            maxLength: 8192
                          last_call_at:
                            type: string
                            maxLength: 8192
                          matched_name:
                            type: string
                            maxLength: 8192
                          alternate_names:
                            type: array
                            maxItems: 1024
                            items:
                              type:
                                - string
                                - number
                                - boolean
                                - object
                                - array
                          name_candidates:
                            type: array
                            maxItems: 1024
                            items:
                              type:
                                - string
                                - number
                                - boolean
                                - object
                                - array
                          timezones:
                            type: array
                            maxItems: 1024
                            items:
                              type:
                                - string
                                - number
                                - boolean
                                - object
                                - array
                          emails:
                            type: array
                            maxItems: 1024
                            items:
                              type:
                                - string
                                - number
                                - boolean
                                - object
                                - array
                          websites:
                            type: array
                            maxItems: 1024
                            items:
                              type:
                                - string
                                - number
                                - boolean
                                - object
                                - array
                          locations:
                            type: array
                            maxItems: 1024
                            items:
                              type:
                                - string
                                - number
                                - boolean
                                - object
                                - array
                          social_profiles:
                            type: array
                            maxItems: 1024
                            items:
                              type:
                                - string
                                - number
                                - boolean
                                - object
                                - array
                          report_count:
                            type: integer
                            minimum: 0
                          tag_count:
                            type: integer
                            minimum: 0
                          total_calls:
                            type: integer
                            minimum: 0
                          calls_60_days:
                            type: integer
                            minimum: 0
                          reports_60_days:
                            type: integer
                            minimum: 0
                          searches_60_days:
                            type: integer
                            minimum: 0
                          comment_count:
                            type: integer
                            minimum: 0
                          names_count:
                            type: integer
                            minimum: 0
                          spam_report_count:
                            type: integer
                            minimum: 0
                    description: >-
                      Only present for a found phone signal. Curated facts about
                      the number, not raw upstream documents and never the
                      provider's identity, scores or verdicts; follows normal
                      record retention/deletion.
                allOf:
                  - if:
                      properties:
                        outcome:
                          const: found
                      required:
                        - outcome
                    then:
                      required:
                        - evidence_ref
                        - observed_at
                        - last_checked_at
                      properties:
                        freshness:
                          enum:
                            - fresh
                            - stale
                      not:
                        required:
                          - reason
                      description: >-
                        A definite presence: evidence exists, so its freshness
                        is known.
                  - if:
                      properties:
                        outcome:
                          const: not_found
                      required:
                        - outcome
                    then:
                      required:
                        - last_checked_at
                      not:
                        anyOf:
                          - required:
                              - reason
                          - required:
                              - evidence_ref
                      description: >-
                        A definite absence. Carries no failure reason: a
                        timeout, block or error is never encoded as not_found.
                  - if:
                      properties:
                        outcome:
                          enum:
                            - inconclusive
                            - blocked
                            - unavailable
                      required:
                        - outcome
                    then:
                      required:
                        - reason
                  - if:
                      properties:
                        outcome:
                          enum:
                            - blocked
                            - unavailable
                      required:
                        - outcome
                    then:
                      properties:
                        freshness:
                          const: unknown
                      not:
                        anyOf:
                          - required:
                              - evidence_ref
                          - required:
                              - observed_at
                      description: >-
                        No evidence was obtained, so there is nothing observed
                        and nothing to reference.
                  - if:
                      required:
                        - enrichment
                    then:
                      properties:
                        identifier:
                          const: phone
                        outcome:
                          const: found
              description: >-
                Detailed view only (response_mode=detailed, which needs the
                detailed scope): a standard answer omits signals[], and a
                detailed one always carries it, possibly empty. At most one
                signal per (type, source_id, identifier).
            incomplete_sources:
              type: array
              maxItems: 256
              items:
                type: object
                additionalProperties: false
                required:
                  - lane
                  - reason
                description: >-
                  One lane that did not settle, and why. It names a lane, never
                  a source: the (source, identifier) pairs behind it stay
                  internal. A lane is listed once. A lane that missed the 10 s
                  lane deadline is timed_out, never not_found.
                properties:
                  lane:
                    enum:
                      - accounts
                      - phone
                      - breach
                      - ip
                    description: >-
                      An evidence lane: accounts (account presence for email and
                      username), phone, breach and ip.
                  reason:
                    enum:
                      - timed_out
                      - rate_limited
                      - blocked
                      - source_error
                      - unavailable
                      - deferred
                    description: >-
                      Why a lane did not settle. insufficient_evidence is a
                      settled verdict (an inconclusive signal), never a reason
                      to list a lane as incomplete. deferred means the lane is
                      async-only and still running; a continuation settles it.
                      timed_out means the lane missed its deadline.
              description: >-
                The lanes that did not settle, each listed once with a reason;
                never a source. In a detailed view a lane is listed exactly when
                one of its signals did not settle; a standard view carries no
                signals to match.
            policy_version:
              type: string
              minLength: 1
              maxLength: 64
              pattern: ^[a-z0-9][a-z0-9._-]{0,63}(\+t[1-9][0-9]{0,8})?$
              description: >-
                Version of the hand-authored heuristic weights that produced the
                recommendation, for example 'risk-2026-10.7'. A workspace
                threshold override adds a +t<N> suffix, e.g.
                'risk-2026-10.7+t3'.
              not:
                description: >-
                  A line feed anywhere, refused with `not` beside every anchored
                  pattern.
                pattern: \n
            policy_basis:
              const: heuristic_unvalidated
            assessment_version:
              type: integer
              minimum: 1
              maximum: 1000
              description: >-
                Monotonic revision of this assessment. 1 on the synchronous
                answer; each material change while the assessment is served (an
                async continuation settling a source, a change of
                recommendation, confidence or status) increments it. Expiry does
                not increment it: an expired assessment is gone, not revised,
                and the expiry webhook carries the last served version.
            created_at:
              type: string
              format: date-time
              description: >-
                When the assessment was created. Fixed for the life of the
                assessment: every revision carries the same created_at.
            updated_at:
              type: string
              format: date-time
            expires_at:
              type: string
              format: date-time
              description: >-
                After this instant the assessment is no longer served: GET
                /v1/assessments/{assessment_id} answers 404 and it leaves the
                account history. It is created_at plus the workspace's retention
                period at creation (default 365 days, at most 365). Fixed per
                record: a later async revision never extends it, and a new
                assessment for the same account never renews an older one. If
                the workspace later shortens retention, the effective expiry
                becomes created_at + min(retention at creation, current
                retention).
            assessment_url:
              type: string
              maxLength: 64
              pattern: ^/v1/assessments/asm_[0-9A-HJKMNP-TV-Z]{26}$
              description: >-
                Server-relative path of the authoritative assessment, GET
                /v1/assessments/{assessment_id}.
              not:
                description: >-
                  A line feed anywhere, refused with `not` beside every anchored
                  pattern.
                pattern: \n
            timing:
              type: object
              additionalProperties: false
              required:
                - deadline_ms
                - elapsed_ms
              properties:
                deadline_ms:
                  type: integer
                  minimum: 50
                  maximum: 3000
                  description: The budget the server applied to the synchronous answer.
                elapsed_ms:
                  type: integer
                  minimum: 0
                  maximum: 600000
                  description: >-
                    Server time from HTTP ingress to this revision of the
                    assessment.
            auth_context:
              type: object
              additionalProperties: false
              required:
                - provider
                - issuer
                - verified
                - transport
              description: >-
                The identity fields of the auth context the assessment was made
                with, echoed for the workspace's own correlation: the request's
                auth_context, or the one a hosted provider hook (POST
                /hooks/{integration_id}) built, with transport provider_hook and
                its hook_point. Present exactly when the request carried an
                auth_context, and the same on every revision of the assessment.
                Values are as the request or the hook sent them; tokens,
                timestamps, roles and scopes are not echoed, and the echo does
                not change the score.
              properties:
                provider:
                  type: string
                  pattern: ^[a-z0-9][a-z0-9._-]{1,31}$
                  description: The provider slug the context named.
                issuer:
                  type: string
                  maxLength: 256
                  pattern: ^https://[^\s]+$
                  description: The issuer the context named.
                subject:
                  type: string
                  maxLength: 256
                  pattern: ^[A-Za-z0-9._:@/|+=~-]{1,256}$
                  description: >-
                    The subject the context named; absent when it named none (a
                    pre_registration hook).
                session_id:
                  type: string
                  maxLength: 256
                  pattern: ^[A-Za-z0-9._:@/|+=~-]{1,256}$
                  description: The session identifier the context named, when it named one.
                organization_id:
                  type: string
                  maxLength: 256
                  pattern: ^[A-Za-z0-9._:@/|+=~-]{1,256}$
                  description: >-
                    The organization identifier the context named, when it named
                    one.
                verified:
                  type: boolean
                  description: >-
                    The verified flag the context carried. A provider_hook
                    context is always false.
                transport:
                  type: string
                  enum:
                    - backend
                    - browser
                    - provider_hook
                  description: >-
                    Where the context was derived: backend (also when the
                    request named no transport), browser, or provider_hook for a
                    hosted provider hook.
                hook_point:
                  type: string
                  enum:
                    - pre_registration
                    - post_registration
                    - pre_login
                    - post_login
                    - token_issuance
                  description: >-
                    The provider event a provider_hook context was sent for;
                    absent for any other transport.
              if:
                properties:
                  transport:
                    const: provider_hook
              then:
                required:
                  - hook_point
                properties:
                  verified:
                    const: false
              else:
                not:
                  required:
                    - hook_point
          allOf:
            - if:
                properties:
                  status:
                    const: complete
                required:
                  - status
              then:
                required:
                  - recommendation
                properties:
                  incomplete_sources:
                    items:
                      properties:
                        reason:
                          not:
                            const: deferred
                    description: >-
                      A complete assessment may list lanes that failed or timed
                      out, never one still running.
                not:
                  required:
                    - assessment_url
            - if:
                properties:
                  status:
                    const: partial
                required:
                  - status
              then:
                required:
                  - recommendation
                properties:
                  incomplete_sources:
                    minItems: 1
            - if:
                properties:
                  status:
                    const: pending
                required:
                  - status
              then:
                required:
                  - assessment_url
                not:
                  anyOf:
                    - required:
                        - recommendation
                    - required:
                        - risk
                properties:
                  confidence:
                    const: unavailable
                  incomplete_sources:
                    minItems: 1
            - if:
                properties:
                  confidence:
                    const: unavailable
                required:
                  - confidence
              then:
                properties:
                  recommendation:
                    const: review
            - if:
                properties:
                  risk:
                    required:
                      - details
                required:
                  - risk
              then:
                required:
                  - signals
    Problem:
      title: Problem details error
      description: >-
        RFC 9457 problem-details error body returned by every non-2xx API
        response, extended with a stable machine code and request id.
      type: object
      additionalProperties: false
      required:
        - type
        - title
        - status
        - detail
        - code
        - request_id
      properties:
        type:
          type: string
          format: uri-reference
        title:
          type: string
        status:
          type: integer
          minimum: 400
          maximum: 599
        detail:
          type: string
        instance:
          type: string
          format: uri-reference
        code:
          type: string
        request_id:
          type: string
          minLength: 1
        invalid_params:
          type: array
          items:
            type: object
            additionalProperties: false
            required:
              - field
              - reason
            properties:
              field:
                type: string
                minLength: 1
              reason:
                type: string
                minLength: 1
              example:
                type: string
                minLength: 1
  securitySchemes:
    tenantBearer:
      type: http
      scheme: bearer
      description: >-
        Your API key, sent as `Authorization: Bearer <key>`. A key is
        `nrk_live_` or `nrk_test_`, a 26-character key id, `_` and a
        43-character secret. A key sees only its own environment's data.


        Each key has one or more scopes: `assess` creates and reads assessments,
        records outcomes and reports key usage; `history` reads assessments, an
        account's current risk and an account's history, and erases an account;
        `detailed` adds the detailed view; `webhooks` registers, tests, rotates
        and deletes webhook endpoints; `integrations` registers and manages
        hosted provider integrations. A missing, unknown, revoked or expired key
        answers 401. A valid key without the scope an operation needs answers
        403.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.