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

# Create a verification

> Create a verification and get the link to send. Its settings are fixed once created; to change them, create another.



## OpenAPI

````yaml /api-reference/openapi.json post /v1/verifications
openapi: 3.1.0
info:
  title: rial API
  version: 0.1.0
  description: 'Prove a photo is real. Base URL: https://api.rial.io'
  contact:
    name: rial-platform team
    url: https://github.com/Rial-ventures-Inc/rial-platform
  license:
    name: UNLICENSED — proprietary, internal use only
servers:
  - url: https://api.rial.io
    description: Production
security: []
tags:
  - name: Verifications
    description: >-
      Create, fetch, list, and finalize verifications. The core of the API —
      every tenant integration starts here.
  - name: Templates
    description: >-
      Publish, update, revoke and inspect link templates — the reusable capture
      links behind `/l/{token}` (a compact JWT carrying the org and template
      slugs; the legacy `/l/{org}/{slug}` keeps resolving). Callable with a
      secret key; each publish snapshots a versioned capture spec (GET-83).
  - name: Databases
    description: >-
      Create, update, inspect and synchronize tenant-scoped databases used by
      reusable verification templates. Callable with a dashboard session or
      secret API key.
paths:
  /v1/verifications:
    post:
      tags:
        - Verifications
      summary: Create a verification
      description: >-
        Create a verification and get the link to send. Its settings are fixed
        once created; to change them, create another.
      requestBody:
        required: true
        description: >-
          Send `steps` for guided photos, or `max_captures` for N anonymous
          photos (default 1) — never both. Everything else is optional.
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateVerificationRequest'
            example:
              max_captures: 3
              expires_in_seconds: 3600
              signals_required:
                - screen
                - ai
              context:
                kind: damage_claim
                summary: Toyota Corolla front bumper
              webhook_url: https://api.acmeinsurance.com/rial/webhooks
              metadata:
                claim_id: CLM-9912
      responses:
        '201':
          description: >-
            Verification minted. Returns the canonical wire shape including the
            `capture_url` the tenant sends to the end-user.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeveloperVerification'
              example:
                id: vfy_01HXYZABCDEFGHJKMNPQRSTVWX
                status: pending
                capture_url: https://verify.rial.io/v/vfy_01HXYZABCDEFGHJKMNPQRSTVWX
                created_at: '2026-09-16T19:06:57.718Z'
                expires_at: '2026-09-16T20:06:57.718Z'
                captures_count: 0
        '400':
          description: Request body failed Zod validation.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error:
                  code: invalid_request
                  message: Request body failed validation
                  fields:
                    - path: config.max_captures
                      message: must be ≤ 20
        '401':
          description: No valid session / API key / bot HMAC.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error:
                  code: unauthorized
                  message: Missing or invalid API key
        '402':
          description: >-
            plan_limit_reached or insufficient_credits: monthly plan quota and
            legacy credits cannot cover another image.
        '429':
          description: >-
            Tenant rate limit exceeded. Response carries `Retry-After:
            <seconds>` per RFC 7231.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error:
                  code: too_many_requests
                  message: >-
                    Rate limit exceeded for this tenant. Retry after the
                    specified interval.
      security:
        - bearerApiKey: []
components:
  schemas:
    CreateVerificationRequest:
      type: object
      properties:
        max_captures:
          type: integer
          minimum: 1
          maximum: 20
          description: >-
            How many anonymous photos to ask for. Use this or `steps`, never
            both. Default 1.
        steps:
          type: array
          items:
            anyOf:
              - type: object
                properties:
                  label:
                    type: string
                    minLength: 1
                    maxLength: 200
                    description: Visible title of the step.
                  screen:
                    type: object
                    properties:
                      key:
                        type: string
                        minLength: 1
                        maxLength: 64
                        pattern: ^[a-z0-9][a-z0-9_-]*$
                      title:
                        type: string
                        minLength: 1
                        maxLength: 120
                      description:
                        type: string
                        maxLength: 8000
                    required:
                      - key
                      - title
                    additionalProperties: false
                    description: >-
                      Groups consecutive steps on one screen: `key` and `title`
                      shared by the group.
                  when:
                    type: object
                    properties:
                      key:
                        type: string
                        minLength: 1
                        maxLength: 64
                        pattern: ^[a-z0-9][a-z0-9_-]*$
                      value:
                        type: string
                        minLength: 1
                        maxLength: 64
                        pattern: ^[a-z0-9][a-z0-9_-]*$
                    required:
                      - key
                      - value
                    additionalProperties: false
                    description: >-
                      Show this step only when the step `key` was answered with
                      `value`.
                  key:
                    type: string
                    minLength: 1
                    maxLength: 64
                    pattern: ^[a-z0-9][a-z0-9_-]*$
                    description: >-
                      Stable id of the step. Its answer or photos come back
                      under this key.
                  type:
                    type: string
                    enum:
                      - image
                    default: image
                  description:
                    type: string
                    maxLength: 500
                    default: ''
                    description: Instruction shown to the person.
                  min:
                    type: integer
                    minimum: 0
                    description: Minimum photos. 0 makes the step optional.
                  max:
                    type: integer
                    minimum: 1
                    description: Maximum photos.
                  allow_upload:
                    type: boolean
                    description: >-
                      Also allow picking a file from the gallery instead of the
                      camera.
                  accept:
                    type: array
                    items:
                      type: string
                      enum:
                        - image/jpeg
                        - image/png
                        - image/webp
                        - image/heic
                        - image/heif
                    minItems: 1
                    description: Accepted media types.
                  max_size_bytes:
                    type: integer
                    minimum: 1
                    maximum: 26214400
                    description: Maximum size per photo, in bytes.
                  expected_object:
                    type: string
                    minLength: 1
                    maxLength: 200
                    description: >-
                      What must appear in this photo. Overrides the
                      verification-level value.
                  condition_aspects:
                    type: array
                    items:
                      type: string
                      minLength: 1
                      maxLength: 40
                    minItems: 1
                    maxItems: 6
                    description: >-
                      Aspects to score on this photo. Overrides the
                      verification-level value.
                required:
                  - key
                  - min
                  - max
                additionalProperties: false
              - type: object
                properties:
                  label:
                    type: string
                    minLength: 1
                    maxLength: 200
                    description: Visible title of the step.
                  screen:
                    type: object
                    properties:
                      key:
                        type: string
                        minLength: 1
                        maxLength: 64
                        pattern: ^[a-z0-9][a-z0-9_-]*$
                      title:
                        type: string
                        minLength: 1
                        maxLength: 120
                      description:
                        type: string
                        maxLength: 8000
                    required:
                      - key
                      - title
                    additionalProperties: false
                    description: >-
                      Groups consecutive steps on one screen: `key` and `title`
                      shared by the group.
                  when:
                    type: object
                    properties:
                      key:
                        type: string
                        minLength: 1
                        maxLength: 64
                        pattern: ^[a-z0-9][a-z0-9_-]*$
                      value:
                        type: string
                        minLength: 1
                        maxLength: 64
                        pattern: ^[a-z0-9][a-z0-9_-]*$
                    required:
                      - key
                      - value
                    additionalProperties: false
                    description: >-
                      Show this step only when the step `key` was answered with
                      `value`.
                  key:
                    type: string
                    minLength: 1
                    maxLength: 64
                    pattern: ^[a-z0-9][a-z0-9_-]*$
                    description: >-
                      Stable id of the step. Its answer or photos come back
                      under this key.
                  type:
                    type: string
                    enum:
                      - text
                  description:
                    type: string
                    maxLength: 500
                    default: ''
                    description: Instruction shown to the person.
                  required:
                    type: boolean
                    default: true
                    description: Default true.
                  validation:
                    type: object
                    properties:
                      min_length:
                        type: integer
                        minimum: 0
                        maximum: 2000
                      max_length:
                        type: integer
                        minimum: 1
                        maximum: 2000
                      format:
                        type: string
                        enum:
                          - free_text
                          - numeric_id
                          - alphanumeric_id
                          - email
                        default: free_text
                    default:
                      format: free_text
                    additionalProperties: false
                    description: >-
                      Length and format rules: `free_text`, `numeric_id`,
                      `alphanumeric_id` or `email`.
                  variant:
                    type: string
                    enum:
                      - short
                      - long
                    description: '`short` (one line) or `long`.'
                required:
                  - key
                  - type
                additionalProperties: false
              - type: object
                properties:
                  label:
                    type: string
                    minLength: 1
                    maxLength: 200
                    description: Visible title of the step.
                  screen:
                    type: object
                    properties:
                      key:
                        type: string
                        minLength: 1
                        maxLength: 64
                        pattern: ^[a-z0-9][a-z0-9_-]*$
                      title:
                        type: string
                        minLength: 1
                        maxLength: 120
                      description:
                        type: string
                        maxLength: 8000
                    required:
                      - key
                      - title
                    additionalProperties: false
                    description: >-
                      Groups consecutive steps on one screen: `key` and `title`
                      shared by the group.
                  when:
                    type: object
                    properties:
                      key:
                        type: string
                        minLength: 1
                        maxLength: 64
                        pattern: ^[a-z0-9][a-z0-9_-]*$
                      value:
                        type: string
                        minLength: 1
                        maxLength: 64
                        pattern: ^[a-z0-9][a-z0-9_-]*$
                    required:
                      - key
                      - value
                    additionalProperties: false
                    description: >-
                      Show this step only when the step `key` was answered with
                      `value`.
                  key:
                    type: string
                    minLength: 1
                    maxLength: 64
                    pattern: ^[a-z0-9][a-z0-9_-]*$
                    description: >-
                      Stable id of the step. Its answer or photos come back
                      under this key.
                  type:
                    type: string
                    enum:
                      - upload
                  input:
                    type: string
                    enum:
                      - signature
                    description: >-
                      `signature` shows a signature pad instead of a file
                      picker.
                  description:
                    type: string
                    maxLength: 500
                    default: ''
                    description: Instruction shown to the person.
                  min:
                    type: integer
                    minimum: 0
                    description: Minimum files. 0 makes the step optional.
                  max:
                    type: integer
                    minimum: 1
                    description: Maximum files.
                  accept:
                    type: array
                    items:
                      type: string
                      enum:
                        - image/jpeg
                        - image/png
                        - image/webp
                        - image/heic
                        - image/heif
                    minItems: 1
                    default:
                      - image/jpeg
                      - image/png
                      - image/webp
                      - image/heic
                      - image/heif
                    description: Accepted media types.
                  max_size_bytes:
                    type: integer
                    minimum: 1
                    maximum: 26214400
                    default: 10485760
                    description: Maximum size per file, in bytes.
                required:
                  - key
                  - type
                  - min
                  - max
                additionalProperties: false
              - type: object
                properties:
                  label:
                    type: string
                    minLength: 1
                    maxLength: 200
                    description: Visible title of the step.
                  screen:
                    type: object
                    properties:
                      key:
                        type: string
                        minLength: 1
                        maxLength: 64
                        pattern: ^[a-z0-9][a-z0-9_-]*$
                      title:
                        type: string
                        minLength: 1
                        maxLength: 120
                      description:
                        type: string
                        maxLength: 8000
                    required:
                      - key
                      - title
                    additionalProperties: false
                    description: >-
                      Groups consecutive steps on one screen: `key` and `title`
                      shared by the group.
                  when:
                    type: object
                    properties:
                      key:
                        type: string
                        minLength: 1
                        maxLength: 64
                        pattern: ^[a-z0-9][a-z0-9_-]*$
                      value:
                        type: string
                        minLength: 1
                        maxLength: 64
                        pattern: ^[a-z0-9][a-z0-9_-]*$
                    required:
                      - key
                      - value
                    additionalProperties: false
                    description: >-
                      Show this step only when the step `key` was answered with
                      `value`.
                  key:
                    type: string
                    minLength: 1
                    maxLength: 64
                    pattern: ^[a-z0-9][a-z0-9_-]*$
                    description: >-
                      Stable id of the step. Its answer or photos come back
                      under this key.
                  type:
                    type: string
                    enum:
                      - video
                  description:
                    type: string
                    maxLength: 500
                    default: ''
                    description: Instruction shown to the person.
                  min:
                    type: integer
                    minimum: 0
                    description: Minimum clips. 0 makes the step optional.
                  max:
                    type: integer
                    minimum: 1
                    description: Maximum clips.
                  max_duration_sec:
                    type: integer
                    minimum: 1
                    maximum: 30
                    default: 30
                    description: Maximum length of each clip, in seconds.
                required:
                  - key
                  - type
                  - min
                  - max
                additionalProperties: false
              - type: object
                properties:
                  label:
                    type: string
                    minLength: 1
                    maxLength: 200
                    description: Visible title of the step.
                  screen:
                    type: object
                    properties:
                      key:
                        type: string
                        minLength: 1
                        maxLength: 64
                        pattern: ^[a-z0-9][a-z0-9_-]*$
                      title:
                        type: string
                        minLength: 1
                        maxLength: 120
                      description:
                        type: string
                        maxLength: 8000
                    required:
                      - key
                      - title
                    additionalProperties: false
                    description: >-
                      Groups consecutive steps on one screen: `key` and `title`
                      shared by the group.
                  when:
                    type: object
                    properties:
                      key:
                        type: string
                        minLength: 1
                        maxLength: 64
                        pattern: ^[a-z0-9][a-z0-9_-]*$
                      value:
                        type: string
                        minLength: 1
                        maxLength: 64
                        pattern: ^[a-z0-9][a-z0-9_-]*$
                    required:
                      - key
                      - value
                    additionalProperties: false
                    description: >-
                      Show this step only when the step `key` was answered with
                      `value`.
                  key:
                    type: string
                    minLength: 1
                    maxLength: 64
                    pattern: ^[a-z0-9][a-z0-9_-]*$
                    description: >-
                      Stable id of the step. Its answer or photos come back
                      under this key.
                  type:
                    type: string
                    enum:
                      - choice
                  description:
                    type: string
                    maxLength: 500
                    default: ''
                    description: Instruction shown to the person.
                  required:
                    type: boolean
                    default: true
                    description: Default true.
                  multiple:
                    type: boolean
                    default: false
                    description: Allow picking more than one option.
                  options:
                    type: array
                    items:
                      type: object
                      properties:
                        key:
                          type: string
                          minLength: 1
                          maxLength: 64
                          pattern: ^[a-z0-9][a-z0-9_-]*$
                        label:
                          type: string
                          minLength: 1
                          maxLength: 500
                      required:
                        - key
                        - label
                      additionalProperties: false
                    minItems: 1
                    maxItems: 50
                    description: Options to pick from, each with `key` and `label`.
                required:
                  - key
                  - type
                  - options
                additionalProperties: false
              - type: object
                properties:
                  label:
                    type: string
                    minLength: 1
                    maxLength: 200
                    description: Visible title of the step.
                  screen:
                    type: object
                    properties:
                      key:
                        type: string
                        minLength: 1
                        maxLength: 64
                        pattern: ^[a-z0-9][a-z0-9_-]*$
                      title:
                        type: string
                        minLength: 1
                        maxLength: 120
                      description:
                        type: string
                        maxLength: 8000
                    required:
                      - key
                      - title
                    additionalProperties: false
                    description: >-
                      Groups consecutive steps on one screen: `key` and `title`
                      shared by the group.
                  when:
                    type: object
                    properties:
                      key:
                        type: string
                        minLength: 1
                        maxLength: 64
                        pattern: ^[a-z0-9][a-z0-9_-]*$
                      value:
                        type: string
                        minLength: 1
                        maxLength: 64
                        pattern: ^[a-z0-9][a-z0-9_-]*$
                    required:
                      - key
                      - value
                    additionalProperties: false
                    description: >-
                      Show this step only when the step `key` was answered with
                      `value`.
                  key:
                    type: string
                    minLength: 1
                    maxLength: 64
                    pattern: ^[a-z0-9][a-z0-9_-]*$
                    description: >-
                      Stable id of the step. Its answer or photos come back
                      under this key.
                  type:
                    type: string
                    enum:
                      - address
                  country:
                    type: string
                    enum:
                      - BR
                    description: '`BR` shows Brazilian address fields.'
                  description:
                    type: string
                    maxLength: 500
                    default: ''
                    description: Instruction shown to the person.
                  required:
                    type: boolean
                    default: true
                    description: Default true.
                required:
                  - key
                  - type
                additionalProperties: false
          minItems: 1
          description: >-
            Guided steps in order: photos, text questions, uploads, choices,
            addresses. Use this or `max_captures`.
        expires_in_seconds:
          type: integer
          minimum: 60
          maximum: 86400
          default: 3600
          description: >-
            How long the capture link stays open, in seconds. Default 3600 (one
            hour), max 86400.
        signals_required:
          type: array
          items:
            type: string
            enum:
              - screen
              - ai
              - reverse
              - context
          minItems: 1
          default:
            - screen
            - ai
          description: >-
            Checks to run on each photo: `screen` (photo of a screen), `ai`
            (AI-generated), `reverse` (already online), `context` (matches
            `context`). Default `["screen", "ai"]`.
        seal:
          type: boolean
          default: true
          description: Stamp the delivered photos with a C2PA seal. Default true.
        mode:
          type: string
          enum:
            - verification
            - audit
          description: >-
            `verification` (photo taken live, default) or `audit` (a file that
            already exists, uploaded through the API).
        context:
          type: object
          properties:
            kind:
              type: string
              minLength: 1
              maxLength: 64
            summary:
              type: string
              minLength: 1
              maxLength: 500
            attributes:
              type: object
              additionalProperties:
                anyOf:
                  - type: string
                  - type: number
                  - type: boolean
          required:
            - kind
            - summary
          description: >-
            What the photo is supposed to show, for the `context` check: `kind`
            names the thing, `summary` describes it in one line.
        webhook_url:
          type: string
          format: uri
          description: >-
            HTTPS URL that receives `verification.created` and
            `verification.completed`.
        notify_email:
          type:
            - string
            - 'null'
          maxLength: 254
          format: email
          description: >-
            Email that receives the result. `null` opts this verification out;
            absent uses your account default.
        notify_subject_template:
          type:
            - string
            - 'null'
          minLength: 1
          description: Subject of the result email. `{variable}` placeholders allowed.
        notify_body_template:
          type:
            - string
            - 'null'
          minLength: 1
          description: Body of the result email. `{variable}` placeholders allowed.
        completion_message:
          type:
            - string
            - 'null'
          minLength: 1
          maxLength: 2000
          description: >-
            Full plain-text message shown after submitting content. HTML,
            markdown and variables are not interpreted. Omit on create or send
            null on PATCH to use the default.
        metadata:
          type: object
          additionalProperties:
            type: string
            maxLength: 500
          description: >-
            Your own key/value strings, returned with every result and webhook.
            Example: `{ "claim_id": "CLM-9912" }`.
        requires_location:
          type: boolean
          description: >-
            Require a GPS fix on the first photo without comparing it to an
            address.
        expected_location:
          type: string
          minLength: 1
          maxLength: 300
          description: >-
            Street address the photo must be taken at. Turns on
            `location_match`.
        expected_object:
          type: string
          minLength: 1
          maxLength: 200
          description: >-
            What must appear in the photo, e.g. `"car"`. Turns on
            `object_match`.
        condition_aspects:
          type: array
          items:
            type: string
            minLength: 1
            maxLength: 40
          minItems: 1
          maxItems: 6
          description: >-
            One to six aspects to score from 0 to 10, e.g. `["paint", "tires"]`.
            Turns on `condition`.
        expected_info:
          type: object
          properties:
            source:
              type: string
              enum:
                - individual
                - csv
              default: individual
            shared:
              type: object
              properties:
                expected_location:
                  type: string
                  minLength: 1
                  maxLength: 300
                expected_object:
                  type: string
                  minLength: 1
                  maxLength: 200
                condition_aspects:
                  type: array
                  items:
                    type: string
                    minLength: 1
                    maxLength: 40
                  minItems: 1
                  maxItems: 6
                ocr_type:
                  type: string
                  minLength: 1
                  maxLength: 40
              additionalProperties: false
            subject:
              type: object
              properties:
                expected_location:
                  type: string
                  minLength: 1
                  maxLength: 300
                expected_object:
                  type: string
                  minLength: 1
                  maxLength: 200
                condition_aspects:
                  type: array
                  items:
                    type: string
                    minLength: 1
                    maxLength: 40
                  minItems: 1
                  maxItems: 6
                ocr_type:
                  type: string
                  minLength: 1
                  maxLength: 40
                asset_ref:
                  type: string
                  minLength: 1
                  maxLength: 120
                person:
                  type: object
                  properties:
                    name:
                      type: string
                      minLength: 1
                      maxLength: 120
                    email:
                      type: string
                      maxLength: 254
                      format: email
                    phone_e164:
                      type: string
                      pattern: ^\+[1-9]\d{6,14}$
                    external_ref:
                      type: string
                      minLength: 1
                      maxLength: 120
                  additionalProperties: false
              additionalProperties: false
          additionalProperties: false
          description: >-
            Structured alternative to `expected_location`, `expected_object` and
            `condition_aspects`. Send one form or the other.
        brand_slug:
          type: string
          minLength: 2
          maxLength: 40
          pattern: ^[a-z0-9]+(?:-[a-z0-9]+)*$
          description: >-
            Brand profile shown on the capture page. Absent = your default
            brand.
      additionalProperties: false
      description: >-
        Body for `POST /v1/verifications`. All fields optional — sensible
        defaults: `max_captures: 1`, `expires_in_seconds: 3600`,
        `signals_required: ["screen", "ai"]`. Capture quantity comes as EITHER
        `max_captures` (N anonymous captures) OR `steps` (guided slots with
        key/description/min/max) — never both. `context` is what the analysis
        pipeline cross-references against the capture; `metadata` is opaque
        pass-through echoed back on every webhook event.
    DeveloperVerification:
      type: object
      properties:
        id:
          type: string
          pattern: ^vfy_[0-9A-HJKMNP-TV-Z]{26}$
        status:
          type: string
          enum:
            - pending
            - partially_captured
            - completed
            - expired
            - failed
            - abandoned
          description: >-
            Lifecycle state. `pending` → first capture flips to
            `partially_captured` → analysis sets the verdict and transitions to
            `completed`. Terminal: `completed`, `expired`, `failed`. `abandoned`
            is a side-branch off `pending`/`partially_captured`, reported by the
            capture screen via `POST /v1/verifications/:token/progress` when the
            end user leaves before finishing — NOT terminal: a later capture
            resurrects the row to `partially_captured` like any other.
        capture_url:
          type: string
          format: uri
        created_at:
          type: string
          format: date-time
        expires_at:
          type: string
          format: date-time
        captures_count:
          type: integer
          minimum: 0
        verdict:
          anyOf:
            - type: object
              properties:
                rial:
                  type: boolean
                  description: True when no check tripped.
                signals:
                  type: array
                  items:
                    type: string
                    enum:
                      - screen_detected
                      - ai_detected
                      - found_online
                    description: >-
                      A check that tripped: `screen_detected` (photo of a
                      screen), `ai_detected` (AI-generated), `found_online`
                      (already published).
                  description: The checks that tripped.
              required:
                - rial
                - signals
              description: >-
                Verdict of a live capture. Branch on `rial`; `signals` says why
                when it is false.
            - type: object
              properties:
                signals:
                  type: array
                  items:
                    oneOf:
                      - type: object
                        properties:
                          type:
                            type: string
                            enum:
                              - screen_detected
                        required:
                          - type
                      - type: object
                        properties:
                          type:
                            type: string
                            enum:
                              - ai_detected
                          confidence:
                            type: number
                            minimum: 0
                            maximum: 1
                        required:
                          - type
                          - confidence
                      - type: object
                        properties:
                          type:
                            type: string
                            enum:
                              - found_online
                        required:
                          - type
                    description: A check that tripped on an audited file.
              required:
                - signals
              description: >-
                Verdict of an audit (`mode: "audit"`, a file that already
                existed). No `rial`: with no live capture behind it, the checks
                are reported for you to weigh. Empty `signals` means nothing
                tripped.
        location:
          type: object
          properties:
            lat:
              type: number
            lng:
              type: number
            accuracy_m:
              type: number
              minimum: 0
            derived_from:
              type: string
              enum:
                - exif
                - live
                - last_known_session
                - last_known_system
                - last_known_persisted
            age_ms:
              type: integer
              minimum: 0
            place:
              type: string
          required:
            - lat
            - lng
            - accuracy_m
          description: >-
            Where the photo was taken, from the device. Absent for uploaded
            files and when the device reported no fix.
        location_match:
          type: object
          properties:
            status:
              type: string
              enum:
                - verified
                - no_match
                - ungeocoded
                - rejected
                - not_applicable
            expected_location:
              type: string
            observed_location:
              type: string
            expected_point:
              type: object
              properties:
                lat:
                  type: number
                lng:
                  type: number
              required:
                - lat
                - lng
            observed_point:
              type: object
              properties:
                lat:
                  type: number
                lng:
                  type: number
              required:
                - lat
                - lng
            distance_m:
              type: number
              minimum: 0
            threshold_m:
              type: number
              minimum: 0
            gps_accuracy_m:
              type: number
              minimum: 0
            geocode_ref:
              type: string
            reason:
              type: string
          required:
            - status
          description: >-
            Whether the photo was taken at `expected_location`. `verified`
            within GPS tolerance; `no_match` somewhere else; `ungeocoded` when
            the address or the fix could not be resolved; `rejected` when the
            device reported a mock location.
        object_match:
          type: object
          properties:
            status:
              type: string
              enum:
                - match
                - mismatch
                - inconclusive
            expected_object:
              type: string
          required:
            - status
          description: >-
            Object-check result. Present when an object check was requested
            globally or on an image step. With step-only configuration the
            status is the worst step result and expected_object is omitted.
            Independent of the fraud verdict.
        object_matches:
          type: object
          additionalProperties:
            type: object
            properties:
              status:
                type: string
                enum:
                  - match
                  - mismatch
                  - inconclusive
              expected_object:
                type: string
            required:
              - status
              - expected_object
            description: >-
              Object-check result for one image step, including its expected
              object.
          description: >-
            Object-check results keyed by image step. Missing capture verdicts
            yield inconclusive; otherwise each value is the worst context result
            for the step, ignoring not_applicable when live evidence exists.
        condition:
          type: object
          properties:
            score:
              type: number
              minimum: 0
              maximum: 10
            label:
              type: string
              enum:
                - good
                - fair
                - poor
            aspects:
              type: array
              items:
                type: object
                properties:
                  name:
                    type: string
                  score:
                    type: number
                    minimum: 0
                    maximum: 10
                  reasoning:
                    type: string
                required:
                  - name
                  - score
                  - reasoning
                description: >-
                  One scored aspect of the condition assessment. `name` echoes
                  the free-form tenant-defined aspect from `condition_aspects`
                  verbatim — any language, any domain, no fixed vocabulary.
                  `score` is 0..10 with one decimal; `reasoning` is a
                  one-or-two-sentence visual justification.
            steps:
              type: object
              additionalProperties:
                type: object
                properties:
                  score:
                    type: number
                    minimum: 0
                    maximum: 10
                  label:
                    type: string
                    enum:
                      - good
                      - fair
                      - poor
                  aspects:
                    type: array
                    items:
                      type: object
                      properties:
                        name:
                          type: string
                        score:
                          type: number
                          minimum: 0
                          maximum: 10
                        reasoning:
                          type: string
                      required:
                        - name
                        - score
                        - reasoning
                      description: >-
                        One scored aspect of the condition assessment. `name`
                        echoes the free-form tenant-defined aspect from
                        `condition_aspects` verbatim — any language, any domain,
                        no fixed vocabulary. `score` is 0..10 with one decimal;
                        `reasoning` is a one-or-two-sentence visual
                        justification.
                required:
                  - score
                  - label
                  - aspects
                description: >-
                  Condition assessment. Present only when the verification was
                  created with `condition_aspects` — the free-form
                  tenant-defined aspect names (any language, any domain).
                  `score` is the one-decimal average of aspect scores; `label`
                  buckets it (>=7.5 good, >=5 fair, else poor). Independent of
                  the fraud verdict.
              description: >-
                Condition results keyed by photo step. Each uses only that
                step’s photos and its rubric, falling back to the shared rubric.
                The aggregate averages all assessed aspect scores.
          required:
            - score
            - label
            - aspects
          description: >-
            Condition assessment. Present only when the verification was created
            with `condition_aspects` — the free-form tenant-defined aspect names
            (any language, any domain). `score` is the one-decimal average of
            aspect scores; `label` buckets it (>=7.5 good, >=5 fair, else poor).
            Independent of the fraud verdict.
        video_analysis:
          type: object
          properties:
            capture_id:
              type: string
            frames_extracted:
              type: integer
              minimum: 0
            frames_analyzed:
              type: integer
              minimum: 0
            screen:
              type: object
              properties:
                screen_detected:
                  type: boolean
                confidence:
                  type: number
                  minimum: 0
                  maximum: 1
                decided_at_ms:
                  type: integer
                  minimum: 0
              required:
                - screen_detected
                - confidence
                - decided_at_ms
              description: >-
                Worst-case across sampled frames: one flagged frame flags the
                clip; `decided_at_ms` is the clip position of the deciding
                frame.
            analyzed_at:
              type: string
              format: date-time
          required:
            - capture_id
            - frames_extracted
            - frames_analyzed
            - analyzed_at
          description: >-
            Screen-detection analysis of a video-step clip, sampled at one frame
            per second. Written asynchronously after capture — poll or use
            webhooks; absent until the worker has run.
        ocr_primary:
          type: string
        answers:
          type: object
          additionalProperties:
            type: object
            properties:
              values:
                type: array
                items:
                  type: string
              address:
                type: object
                properties:
                  street:
                    type: string
                    minLength: 1
                    maxLength: 200
                  number:
                    type: string
                    minLength: 1
                    maxLength: 200
                  neighborhood:
                    type: string
                    minLength: 1
                    maxLength: 200
                  complement:
                    type: string
                    maxLength: 200
                  city:
                    type: string
                    minLength: 1
                    maxLength: 200
                  region:
                    type: string
                    minLength: 1
                    maxLength: 200
                  postal_code:
                    type: string
                    maxLength: 200
                required:
                  - street
                  - number
                  - neighborhood
                  - city
                  - region
                  - postal_code
                additionalProperties: false
              value:
                type: string
                maxLength: 2000
              answered_at:
                type: string
                format: date-time
            required:
              - value
              - answered_at
            description: >-
              One answered text step. `value` is USER-DECLARED — typed by the
              person capturing; unlike live-captured content, it is never
              sensor-attested. Potential PII: it rides the operator/developer
              contracts and the webhook only, never OG cards or third-party
              public surfaces.
        record_seal:
          anyOf:
            - type: object
              properties:
                algorithm:
                  type: string
                  enum:
                    - sha256
                hash:
                  type: string
                  minLength: 64
                  maxLength: 64
                covers:
                  type: array
                  items:
                    type: string
                    enum:
                      - record
                      - answers
                answers_provenance:
                  type: string
                  enum:
                    - user_declared
              required:
                - algorithm
                - hash
                - covers
                - answers_provenance
            - type: object
              properties:
                algorithm:
                  type: string
                  enum:
                    - sha3-512
                hash:
                  type: string
                  minLength: 128
                  maxLength: 128
                covers:
                  type: array
                  items:
                    type: string
                    enum:
                      - record
                      - answers
                answers_provenance:
                  type: string
                  enum:
                    - user_declared
              required:
                - algorithm
                - hash
                - covers
                - answers_provenance
          description: >-
            Integrity seal over the verification record including `answers`.
            Present only when answers exist and sealing is on (`seal !==
            false`). The hash proves the stored answers have not changed — it
            does NOT claim they are true or sensor-attested;
            `answers_provenance` carries that distinction explicitly.
      required:
        - id
        - status
        - capture_url
        - created_at
        - expires_at
        - captures_count
      description: >-
        A verification as your API key sees it. `verdict` appears once analysis
        finished; `object_match`, `location_match` and `condition` appear when
        you asked for them and the check ran. Your `metadata` is not echoed
        back: keep the `id`.
    ErrorResponse:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
            message:
              type: string
            fields:
              type: array
              items:
                type: object
                properties:
                  path:
                    type: string
                  message:
                    type: string
                required:
                  - path
                  - message
          required:
            - code
            - message
      required:
        - error
      description: >-
        Uniform error envelope. `code` is the stable string SDKs branch on
        (`invalid_request`, `unauthorized`, `not_found`, `expired`, `step_full`,
        `unknown_step`, `steps_incomplete`, `already_finalized`,
        `too_many_requests`, `storage_unavailable`, `internal_error`). `fields`
        is only present on `invalid_request` validation failures.
  securitySchemes:
    bearerApiKey:
      type: http
      scheme: bearer
      bearerFormat: rk_secret_<key>
      description: >-
        Secret API key, created in the dashboard under Settings → API. Send it
        as `Authorization: Bearer rk_secret_…` from your server only.
        Publishable keys (`pk_live_…`) are for the native SDKs and reach the
        capture endpoints alone. An unknown key returns 401.

````