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

# Run an instant verification

> Verify someone from the documents you hold, in a single call, and read the result in the reply.

Everything a verification takes arrives at once: the workflow, your reference for the subject, the context you hold, the values the steps take and every document, each naming the step it answers. The checks run before this call returns, so the record you get back is the finished one, with every step's verdict on it. There is nothing to poll and no callback to wait for.

Name each document's step, and its slot only where the step has more than one; the workflow's `intake` names both. Where a slot names several kinds of document, name which of them yours is. Send several documents to the same slot where it takes several, as a certificate whose pages arrive as separate images does; the files in one slot are all of the same kind. The documents themselves are read as they arrive and stored nowhere, so they cannot be downloaded from the record afterwards: what it keeps is each file's name, type and hash, as the record of what was checked.

A submission that cannot be run as it stands is refused before anything runs, naming every step at fault, so a document you left out is answered here rather than by a verification that never finishes. Nothing is checked and nothing is charged for; correct it and send it again.

Every call runs the checks. Sending the same subject again, with the same documents or different ones, is a second verification of them and answers on what that second call carried; nothing is reused from the first. `reference_user_id` is your label for the subject rather than a key, so several records may carry it, and reading them back by that reference lists every time you asked.

A check whose source could not be reached, or which there was no time left to make, leaves its step reading `error` rather than a verdict, and the rest of the record stands. Send the request again to have another go at those.



## OpenAPI

````yaml /verification/api-reference/openapi.json post /verifications/instant
openapi: 3.1.0
info:
  title: Verify with Privue
  description: >-
    Start identity-and-business verifications and read the results.


    There are three ways to run one, and a verification reads the same whichever
    it was. Every workflow declares which it is for as its `mode`, and a
    workflow is one of them and never more.


    **Hosted.** You create a verification with the user's mobile number and
    receive a journey URL to hand to them. They work through the steps your
    workflow configures, on our screens, and submit. Use this when the person
    being verified is reachable and holds their own documents.


    **Staged.** You create a verification, upload each document you hold against
    the step it answers, and ask for the checks to run. They take longer than a
    request should be held open, so you read the result from a callback or by
    polling. Use this when documents reach you over time, or when you want them
    kept on the record to download later.


    **Instant.** You send the whole submission in one request. The checks run
    before it answers, so the reply is the finished record. The documents are
    read as they arrive and stored nowhere. Use this when you hold everything
    already and want the answer in the call you made.


    Whichever it was, you read the whole record: every step, its state, what it
    collected, and why anything did not pass. An instant verification hands you
    that record in its reply; for the other two, poll the verification or
    register a callback endpoint and be told when it is submitted.


    Across your whole account you can list the workflows configured for you,
    count your verifications by status, and page through the records behind a
    count.


    Every error response has the shape `{"code": "...", "detail": "..."}`.
    Branch on `code`: several causes share a status, and `detail` is written for
    a person reading a log rather than for code. Treat a code you do not
    recognise as the status it arrived at.
  version: 0.1.0
servers:
  - url: https://api.verify.privue.ai
    description: Production
security: []
tags:
  - name: Workflows
    description: >-
      The workflows configured for your account. Read one to see its mode, the
      documents it asks for, and how each step is answered over the API: the
      slots its documents go in and the values it takes.
  - name: Verifications
    description: >-
      Starting a verification, ending one, clearing one to run the same subject
      again, and purging one. Shared by both modes. A start answers 201 when it
      created the verification and 200 when the subject already had one, so a
      duplicate is visible from the status code alone.
  - name: Hosted workflows
    description: >-
      For a workflow the person being verified walks themselves. Start a
      verification with their mobile number, hand them the journey URL on the
      record, or open it for them from inside your own app with a handoff.
  - name: Staged workflows
    description: >-
      For a workflow you build up from documents you already hold. Upload each
      file against the step and slot it answers, withdraw one you got wrong,
      then ask for the checks to run and read the result when they have. Nobody
      is sent anywhere.
  - name: Instant workflows
    description: >-
      For a workflow answered in the request that asks it. Send the whole
      submission at once and read the finished record in the reply. Nothing is
      kept of the documents and nothing is left open to come back to.
  - name: Results
    description: >-
      Reading what a verification came to: one record, a page of them, counts
      across your account, and links to the files it holds.
paths:
  /verifications/instant:
    post:
      tags:
        - Instant workflows
      summary: Run an instant verification
      description: >-
        Verify someone from the documents you hold, in a single call, and read
        the result in the reply.


        Everything a verification takes arrives at once: the workflow, your
        reference for the subject, the context you hold, the values the steps
        take and every document, each naming the step it answers. The checks run
        before this call returns, so the record you get back is the finished
        one, with every step's verdict on it. There is nothing to poll and no
        callback to wait for.


        Name each document's step, and its slot only where the step has more
        than one; the workflow's `intake` names both. Where a slot names several
        kinds of document, name which of them yours is. Send several documents
        to the same slot where it takes several, as a certificate whose pages
        arrive as separate images does; the files in one slot are all of the
        same kind. The documents themselves are read as they arrive and stored
        nowhere, so they cannot be downloaded from the record afterwards: what
        it keeps is each file's name, type and hash, as the record of what was
        checked.


        A submission that cannot be run as it stands is refused before anything
        runs, naming every step at fault, so a document you left out is answered
        here rather than by a verification that never finishes. Nothing is
        checked and nothing is charged for; correct it and send it again.


        Every call runs the checks. Sending the same subject again, with the
        same documents or different ones, is a second verification of them and
        answers on what that second call carried; nothing is reused from the
        first. `reference_user_id` is your label for the subject rather than a
        key, so several records may carry it, and reading them back by that
        reference lists every time you asked.


        A check whose source could not be reached, or which there was no time
        left to make, leaves its step reading `error` rather than a verdict, and
        the rest of the record stands. Send the request again to have another go
        at those.
      operationId: run_verification_verifications_instant_post
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RunVerificationRequest'
        required: true
      responses:
        '201':
          description: The finished record, with every step checked and its verdict on it.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VerificationRecord'
              example:
                id: 0b4d7c62-9a15-4e38-b7f0-3c8e1d05a94b
                mode: instant
                status: completed
                workflow_key: vendor-check
                version: 1
                mobile: null
                reference_user_id: VENDOR-4471
                context: {}
                return_url: null
                journey_url: null
                created_at: '2026-08-27T11:02:09'
                last_activity_at: '2026-08-27T11:06:40'
                expires_after_days: 30
                run_requested_at: '2026-08-27T11:06:40'
                submitted_at: '2026-08-27T11:07:52'
                completed_at: '2026-08-27T11:07:52'
                cancelled_at: null
                gated_at: null
                gated_by_step: null
                failed_at: null
                expired_at: null
                expired_by: null
                acknowledgement: null
                callback: null
                credits_consumed: 1
                resets: 0
                progress:
                  total: 5
                  passed: 5
                  failed: 0
                  awaiting: 0
                  enriching: 0
                  error: 0
                  declined: 0
                  not_supplied: 0
                  undetermined: 0
                  not_applicable: 0
                steps:
                  - key: gst
                    title: GST certificate
                    label: null
                    type: gst-certificate
                    required: false
                    state: passed
                    reasons: []
                    gaps: []
                    collected:
                      answer: {}
                      outputs:
                        gstin: 27AABCA1234F1Z5
                        legal_name: ACME TRADERS PRIVATE LIMITED
                        trade_name: Acme Traders
                        registration_status: Active
                        registration_date: '2020-01-13'
                        business_constitution: Private Limited Company
                        taxpayer_type: Regular
                        e_invoice_mandated: true
                        aggregate_turnover: 'Slab: Rs. 5 Cr. to 25 Cr.'
                        authorized_signatories:
                          - Rahul Mehta
                          - Priya Mehta
                        nature_of_business_activities:
                          - Wholesale Business
                          - Warehouse / Depot
                        business_details:
                          goods_details:
                            - goods_description: Filtering machinery
                              hsn_code: '84212190'
                          service_details: []
                        filings:
                          - return_type: GSTR1
                            financial_year: 2026-2027
                            tax_period: May
                            status: Filed
                            filing_date: '2026-06-04'
                            mode_of_filing: ONLINE
                          - return_type: GSTR3B
                            financial_year: 2026-2027
                            tax_period: May
                            status: Filed
                            filing_date: '2026-06-23'
                            mode_of_filing: ONLINE
                          - return_type: GSTR9
                            financial_year: 2024-2025
                            tax_period: Annual
                            status: Filed
                            filing_date: '2025-12-18'
                            mode_of_filing: ONLINE
                        business_pan: AABCA1234F
                        sole_proprietor_pan: null
                        addresses:
                          - address: 12 Industrial Estate, Pune, Maharashtra 411026
                            tag: Principal Business Address
                        primary_business_address:
                          street: 12 Industrial Estate
                          city: Pune
                          state: Maharashtra
                          country: India
                          postal_code: '411026'
                        other_business_address: null
                        names:
                          - name: ACME TRADERS PRIVATE LIMITED
                            tag: Legal Name
                          - name: Acme Traders
                            tag: Trade Name
                        promoters:
                          - Rahul Mehta
                          - Priya Mehta
                        business_email: accounts@acmetraders.in
                        business_mobile: '9820011223'
                    documents:
                      - id: d1e4a7b2-5c38-4f9e-8a61-2b7c0d3e9f14
                        slot: gst-certificate
                        kind: gst-certificate
                        label: gst_certificate
                        filename: avesco-gst-certificate.pdf
                        content_type: application/pdf
                        size_bytes: 203118
                        sha256: >-
                          1c8f4e2a9b7d63f05e1a4c8b2d7f9e3a6b5c0d1e2f3a4b5c6d7e8f9a0b1c2d3e
                        received_at: '2026-08-27T11:04:52'
                  - key: pan
                    title: PAN card
                    label: null
                    type: pan-card
                    required: true
                    state: passed
                    reasons: []
                    gaps: []
                    collected:
                      answer: {}
                      outputs:
                        pan: AABCA1234F
                        name: ACME TRADERS PRIVATE LIMITED
                        date_of_birth_or_incorporation: '2011-06-14'
                        card_document_id: 4fd79a54-a8a7-4e07-b902-a2e75af3e467
                        status: valid
                        aadhaar_seeded: null
                        names:
                          - name: ACME TRADERS PRIVATE LIMITED
                            tag: PAN Holder
                    documents:
                      - id: 3b9c6e1f-8a24-4d57-b0e3-7f1a5c8d2e69
                        slot: pan-card
                        kind: pan-card
                        label: entity_pan
                        filename: avesco-pan.jpg
                        content_type: image/jpeg
                        size_bytes: 87422
                        sha256: >-
                          7a2d9c4e1f8b3a6d0e5c2b9f4a7d1e8c3b6a9d2f5e8c1b4a7d0e3f6c9b2a5d8e
                        received_at: '2026-08-27T11:05:17'
                  - key: bank
                    title: Bank account
                    label: null
                    type: bank-account
                    required: true
                    state: passed
                    reasons: []
                    gaps: []
                    collected:
                      answer:
                        source: typed
                        account_number: '50100234567890'
                        ifsc: HDFC0001234
                      outputs:
                        source: typed
                        account_number: '50100234567890'
                        ifsc: HDFC0001234
                        registered_name: ACME TRADERS PRIVATE LIMITED
                        names:
                          - name: ACME TRADERS PRIVATE LIMITED
                            tag: Bank Account Holder
                        bank_name: null
                        branch: null
                    documents: []
                  - key: cross-check-proprietor
                    title: Proprietor name check
                    label: null
                    type: name-match
                    required: true
                    state: passed
                    reasons: []
                    gaps: []
                    collected:
                      answer: {}
                      outputs:
                        reference:
                          - name: AVESCO HOSPITEX PRIVATE LIMITED
                            tag: Legal Name
                        matches:
                          - check: Bank account holder
                            name: AVESCO HOSPITEX PRIVATE LIMITED
                            matched_to_tag: Legal Name
                            score: 100
                            matched: true
                    documents: []
                  - key: cross-check-business
                    title: Business name check
                    label: null
                    type: name-match
                    required: true
                    state: passed
                    reasons: []
                    gaps: []
                    collected:
                      answer: {}
                      outputs:
                        reference:
                          - name: AVESCO HOSPITEX PRIVATE LIMITED
                            tag: Legal Name
                        matches:
                          - check: Bank account holder
                            name: AVESCO HOSPITEX PRIVATE LIMITED
                            matched_to_tag: Legal Name
                            score: 100
                            matched: true
                    documents: []
        '400':
          description: >-
            The workflow key is unknown, or the context omits a field the
            workflow's required steps cannot run without, or supplies one in a
            shape the step that reads it cannot use.


            The code is one of `context-incomplete`, `context-value-invalid` or
            `workflow-not-found`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                code: context-incomplete
                detail: >-
                  workflow 'merchant-onboarding' requires context fields that
                  were not supplied: state
        '401':
          description: |-
            The API key is missing, malformed, or revoked.

            The code is `unauthenticated`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                code: unauthenticated
                detail: Missing or malformed Authorization header
        '402':
          description: >-
            The workflow has no prepaid credits left. Either none were ever
            granted for it, or its verifications have used them, their term has
            passed, or we have taken them back. Nothing on the workflow can be
            created or moved on until it is topped up; everything on it stays
            readable. Read the workflow to see where its balance stands.


            The code is `credits-exhausted`.
          content:
            application/json:
              example:
                code: credits-exhausted
                detail: >-
                  the credits for workflow 'merchant-onboarding' are gone; of
                  500 granted, 500 used
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: >-
            The workflow belongs to the other environment. An API key is for
            `uat` or for `production` and reaches only that environment's
            workflows. Or the key is valid but not enrolled for verifications,
            or not set up for exactly one of `uat` and `production`, in which
            case ask us to reissue it.


            The code is one of `environment-mismatch` or `client-not-enrolled`.
          content:
            application/json:
              example:
                code: environment-mismatch
                detail: >-
                  workflow 'merchant-onboarding' is production and this request
                  is for uat
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '409':
          description: >-
            The workflow's `mode` is not `instant`, so it is not run this way.
            Or: The workflow already has as many verifications going as it may:
            `runs.limit` on the workflow is how many, and one of them ending
            frees a place. A verification is going for as long as this call
            takes to answer, so this is how many of these calls the workflow may
            have in flight at once.


            The code is one of `workflow-not-runnable` or `live-limit-reached`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                code: workflow-not-runnable
                detail: >-
                  workflow 'merchant-onboarding' is hosted, so it is not run in
                  a single request
        '413':
          description: >-
            A document is larger than its step accepts, or the documents
            together are more than one request may carry.


            The code is one of `document-too-large` or `request-too-large`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                code: document-too-large
                detail: 'documents.0: the file exceeds the 20 MB limit'
        '415':
          description: |-
            A step does not accept a document of this type.

            The code is `document-type-not-allowed`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                code: document-type-not-allowed
                detail: '''Storefront'' does not take pdf files'
        '422':
          description: >-
            The submission cannot be run as it stands: a required step with
            nothing, a slot filled only in part, a step given both values and a
            document, a value that is not valid, a document naming a step the
            workflow does not declare or one that takes no documents, a slot it
            does not have or a kind that slot does not name, or content that is
            not base64. The detail names everything at fault.


            The code is one of `step-invalid` or `request-invalid`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                code: step-invalid
                detail: 'pan: nothing was supplied for this step'
        '429':
          description: |-
            The API key is rate limited. Retry after a pause.

            The code is `rate-limited`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                code: rate-limited
                detail: 'Unauthorized: RATE_LIMITED'
        '500':
          description: >-
            The workflow's output transformations cannot convert a value the
            checks published, so the record cannot be read. The verification
            ends as `failed`, which uses no credit, so sending the request again
            is not charged for this one. Contact us to have the workflow's
            configuration put right.


            The code is `workflow-misconfigured`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                code: workflow-misconfigured
                detail: >-
                  the output transformation for gst-certificate at
                  'registration_date' could not be applied
        '503':
          description: |-
            API keys could not be checked right now. Retry.

            The code is `auth-unavailable`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                code: auth-unavailable
                detail: Auth provider unavailable
      security:
        - HTTPBearer: []
components:
  schemas:
    RunVerificationRequest:
      properties:
        workflow_key:
          type: string
          minLength: 1
          title: Workflow Key
          description: >-
            Which of your workflows the verification runs. Its `mode` must be
            `instant`.
        reference_user_id:
          type: string
          maxLength: 255
          minLength: 1
          title: Reference User Id
          description: >-
            Your own label for the subject of this verification. It is echoed
            back on every response, and together with the workflow key it is the
            handle that survives once the verification has expired, so make it
            something you can reconcile against your own records.


            It is a label rather than a key: every call runs the checks and is
            charged for, so sending the same one again is a second verification
            of that subject and several records may carry it. Listing by it
            reads back every time you asked.
        context:
          additionalProperties: true
          type: object
          title: Context
          description: >-
            Facts you already know about the user, as a flat JSON object.
            Workflow conditions and step inputs can read these values to decide
            what the verification asks for.


            A field one of the workflow's required steps cannot run without is
            refused if you leave it out. Fields no step reads are yours to use
            as you like and are echoed back untouched.
        steps:
          additionalProperties:
            $ref: '#/components/schemas/StepValues'
          type: object
          title: Steps
          description: >-
            Values for the steps that take them, keyed by step key. Each step's
            `intake.values` on the workflow names the values it takes; a step
            whose `intake.values` is empty takes none and has no entry here.


            Leave a step out and it is answered from the documents you sent for
            it. Leave out an optional step entirely, sending no document for it
            either, and it is recorded as not provided. A step that takes both,
            such as a bank account, is answered with one or the other: sending
            values and a document for the same step is refused.
          example:
            bank:
              account_number: '50100234567890'
              ifsc: HDFC0001234
        documents:
          items:
            $ref: '#/components/schemas/CarriedDocument'
          type: array
          maxItems: 12
          title: Documents
          description: >-
            Every document the workflow asks for, at most 12 of them, each
            naming the step it answers. Send several for one slot where that
            slot takes several, as a certificate whose pages arrive as separate
            images does.


            A PDF may be up to 20 MB and an image up to 10 MB, and the documents
            together may total 25 MB once decoded.
      additionalProperties: false
      type: object
      required:
        - workflow_key
        - reference_user_id
      title: RunVerificationRequest
      description: >-
        A whole verification in one request: the subject, the values its steps
        take, and every document.
      examples:
        - context:
            channel: field-sales
            state: MH
          documents:
            - content: /9j/4AAQSkZJRgABAQAAAQ...
              content_type: image/jpeg
              filename: pan-card.jpg
              step_key: pan
            - content: JVBERi0xLjQKJeLjz9MKMy...
              content_type: application/pdf
              filename: gst-certificate.pdf
              step_key: gst
          reference_user_id: merchant-42
          steps:
            bank:
              account_number: '50100234567890'
              ifsc: HDFC0001234
          workflow_key: merchant-onboarding
    VerificationRecord:
      properties:
        id:
          type: string
          format: uuid
          title: Id
          description: The verification's id.
        mode:
          $ref: '#/components/schemas/WorkflowMode'
          description: >-
            How verifications on this workflow are conducted. `hosted`: the
            person being verified walks the journey on our screens and submits
            it. `staged`: you create a verification, upload each document
            against the step it answers, and then ask for the checks to run.
            `instant`: you send the whole submission in one request, which runs
            the checks and answers with the finished record.


            A workflow is one of the three, and every endpoint belonging to
            another is refused on it.
        status:
          $ref: '#/components/schemas/VerificationStatus'
          description: >-
            open while the run is live and the user may act, which a step held
            up by a technical problem does not end; submitted once the user has
            finished, which they can only do with every step settled, so the
            result is final from that moment; completed once the checks that
            follow a submission have run, such as notifying you by callback, and
            the data is safe to read; failed if the run reached an unrecoverable
            state, in which case reset it or create a new one; cancelled if you
            ended the run; gated if a check this workflow puts to a system of
            yours stopped the journey there, which ends the run where it stood.
            A check stops it when your system answers `terminate` or `redirect`,
            or when your system gave no answer and the workflow falls back to
            `terminate`. Poll until the status is one of completed, cancelled,
            gated or failed.


            expired supersedes all of them once the retention window runs out:
            the run is of no further use and is kept for your audit alone. It
            says nothing about how the run had ended, so read completed_at,
            cancelled_at, gated_at or failed_at for that rather than expecting
            the status to hold it.
        workflow_key:
          type: string
          minLength: 1
          title: Workflow Key
          description: The workflow this verification runs.
        version:
          type: integer
          minimum: 1
          title: Version
          description: >-
            Which version of the workflow this verification runs. It is the
            workflow's latest version when the verification was created, and it
            holds for the verification's whole life: a change published to the
            workflow afterwards never changes what this verification asks for,
            which steps it reports or the names its outputs arrive under.
            Resetting the verification moves it onto the latest version at the
            time.
        mobile:
          anyOf:
            - type: string
            - type: 'null'
          title: Mobile
          description: >-
            The user's mobile number, as you provided it. Null on a verification
            you supplied yourself, and null once the verification has expired.
        reference_user_id:
          type: string
          title: Reference User Id
          description: Your identifier for this verification, echoed back.
        context:
          additionalProperties: true
          type: object
          title: Context
          description: >-
            The facts you supplied when you created it, unchanged. Empty once
            the verification has expired.
        return_url:
          anyOf:
            - type: string
            - type: 'null'
          title: Return Url
          description: Where the user is sent after submitting, where one was given.
        journey_url:
          anyOf:
            - type: string
            - type: 'null'
          title: Journey Url
          description: >-
            Where to send your user, on a hosted verification. The same address
            serves every user of this workflow and carries no credential, so it
            is safe to send over WhatsApp, SMS, or email, and the user proves
            who they are by signing in with the mobile number you created the
            verification with. To open the journey from inside your own app with
            the user already signed in, create a handoff instead.


            Null on a verification you supplied yourself, which opens no
            journey.
        created_at:
          type: string
          format: date-time
          title: Created At
          description: When the verification was created.
        run_requested_at:
          anyOf:
            - type: string
              format: date-time
            - type: 'null'
          title: Run Requested At
          description: >-
            When you asked for the checks to run, on a staged verification. From
            that moment the submission is frozen: uploads, withdrawals and a run
            request with different values are refused until you reset.


            On an instant verification it is when the request carrying the whole
            submission arrived. Null on a hosted one, and null on a staged one
            until you ask.
        submitted_at:
          anyOf:
            - type: string
              format: date-time
            - type: 'null'
          title: Submitted At
          description: >-
            When the verification was submitted, if it has been: by the user on
            a hosted workflow, by the run of the checks on one you supplied
            yourself.
        completed_at:
          anyOf:
            - type: string
              format: date-time
            - type: 'null'
          title: Completed At
          description: When the verification completed, if it has.
        cancelled_at:
          anyOf:
            - type: string
              format: date-time
            - type: 'null'
          title: Cancelled At
          description: When the verification was cancelled, if it was.
        gated_at:
          anyOf:
            - type: string
              format: date-time
            - type: 'null'
          title: Gated At
          description: When a check of yours stopped the journey, if one did.
        gated_by_step:
          anyOf:
            - type: string
            - type: 'null'
          title: Gated By Step
          description: >-
            The step whose check stopped the journey, if one did. A workflow may
            put more than one check to you, and this says which of them the run
            stopped at.


            It is set and cleared with `gated_at`: it stays set once the
            verification expires or you purge it, so the record still says how
            the run had ended, and a reset clears both.
        failed_at:
          anyOf:
            - type: string
              format: date-time
            - type: 'null'
          title: Failed At
          description: When the verification was marked failed, if it was.
        expired_at:
          anyOf:
            - type: string
              format: date-time
            - type: 'null'
          title: Expired At
          description: >-
            When the verification expired, if it has. From that moment it is
            kept for your audit and nothing else: it holds what each step
            concluded and nothing the user gave, so no answers, no values read
            off their documents, and no files. The step states you read are the
            ones frozen at that moment. Read the other timestamps to see how it
            had ended before it expired.
        expired_by:
          anyOf:
            - $ref: '#/components/schemas/ExpiryCause'
            - type: 'null'
          description: >-
            What expired the verification. `retention` when its workflow's
            retention window ran out; `client` when you purged it. Null until it
            expires.
        last_activity_at:
          type: string
          format: date-time
          title: Last Activity At
          description: >-
            When the verification was last acted on: by the user on a hosted
            workflow, by you or by the run of the checks on one you supplied
            yourself. A verification that is created and never touched reads the
            moment it was created. `expires_after_days` is counted from here, so
            the two together say when a record left untouched expires.
        expires_after_days:
          type: integer
          minimum: 1
          title: Expires After Days
          description: >-
            How many days this verification may go without activity before it
            expires and everything the user provided is deleted, as the version
            it runs states. It is this verification's own window: a later
            version of its workflow can state a different one, which reaches the
            verifications created or reset after it, so read the window here
            rather than off the workflow. On an expired verification it is the
            window it was held to.
        acknowledgement:
          anyOf:
            - $ref: '#/components/schemas/AcknowledgementRecord'
            - type: 'null'
          description: >-
            The receipt the user was sent telling them their submission arrived,
            on a workflow that acknowledges submissions by email. Null wherever
            nothing has been sent: a workflow that acknowledges nothing, a
            verification carrying no address to send to, a submission still
            being finalised, and a send that could not be made.


            It names the submission it answers. A reset undoes a submission
            without unsending its receipt, so read `submitted_at` here against
            the record's own to tell a receipt for the submission this record
            stands in from one for a submission it no longer does.
        callback:
          anyOf:
            - $ref: '#/components/schemas/CallbackRecord'
            - type: 'null'
          description: >-
            How the callback for this verification's run ended:
            `verification.submitted` once it was submitted, or
            `verification.gated` once a check of yours stopped it. Null until
            the callback settles, and on every verification of a workflow with
            no callback endpoint registered. A verification completes, or stays
            gated, whether or not its callback was delivered, so read this to
            tell a result you were told about from one you were not.
        credits_consumed:
          type: integer
          title: Credits Consumed
          description: >-
            How many credits this verification has used. A run uses one credit
            when it first reaches completed, cancelled or expired, whatever the
            workflow asks for and however many of its checks ran. A run that
            ends as failed or gated uses none, and one still open or submitted
            has used nothing yet.


            Resetting a verification runs the subject through again, which is a
            run of its own and uses a credit of its own, so a record reset twice
            and completed each time reads `3`.
        resets:
          type: integer
          title: Resets
          description: >-
            How many times this verification has been reset. A reset clears
            everything the record collected and runs the subject through the
            checks again, so a verification reading `2` is on its third run and
            holds what that one has collected.


            Each of these opened a run charged a credit of its own where it
            ended, which is what `credits_consumed` counts. A reset that cleared
            a run no credit had paid for also drew one of the workflow's resets:
            see `resets` on the workflow.
        progress:
          $ref: '#/components/schemas/ProgressRecord'
          description: >-
            Every step of the journey counted by where it stands, the ones left
            out included.
        steps:
          items:
            $ref: '#/components/schemas/StepRecord'
          type: array
          title: Steps
          description: >-
            The steps this journey has not ruled out, in journey order. A
            workflow presents the steps that apply to whoever is being verified,
            so a journey that took one branch reports that branch and not the
            others; `progress.not_applicable` says how many are missing from
            here, and reading the verification with `include_not_applicable`
            shows them.


            A step is only missing once something has ruled it out. One whose
            place in the journey turns on a value an earlier step has yet to
            publish is here, reading `undetermined`, so a verification you have
            just created reports every step its workflow declares and they
            resolve into the other states as it goes on.
      type: object
      required:
        - id
        - mode
        - status
        - workflow_key
        - version
        - mobile
        - reference_user_id
        - context
        - return_url
        - journey_url
        - created_at
        - run_requested_at
        - submitted_at
        - completed_at
        - cancelled_at
        - gated_at
        - gated_by_step
        - failed_at
        - expired_at
        - expired_by
        - last_activity_at
        - expires_after_days
        - acknowledgement
        - callback
        - credits_consumed
        - resets
        - progress
        - steps
      title: VerificationRecord
      description: The whole record of one verification; safe to poll.
    ErrorResponse:
      properties:
        code:
          $ref: '#/components/schemas/ErrorCode'
          description: >-
            What went wrong. Branch on this rather than on the status code,
            which several causes share, and never on `detail`.


            Treat a code you do not recognise as the status it arrived at: codes
            are added as new causes become reachable, and an existing one never
            changes meaning.
        detail:
          type: string
          title: Detail
          description: >-
            What went wrong, in words, naming the workflow, verification, step
            or field at fault where one is. Written for a person reading a log
            rather than for code to read, so it is not stable and nothing should
            be matched against it.
      type: object
      required:
        - code
        - detail
      title: ErrorResponse
      description: The envelope every failure is answered in.
    StepValues:
      additionalProperties: true
      type: object
      title: StepValues
      description: >-
        One step's values, under the names that step's `intake.values` lists.


        A bank account step takes `account_number` and `ifsc`; a form step takes
        the fields your workflow declares, under their own names. Read `GET
        /workflows/{workflow_key}` for the names a step takes, and send nothing
        for a step whose `intake.values` is empty.
      example:
        account_number: '50100234567890'
        ifsc: HDFC0001234
    CarriedDocument:
      properties:
        step_key:
          type: string
          minLength: 1
          title: Step Key
          description: The step this document answers.
        slot:
          anyOf:
            - type: string
              minLength: 1
            - type: 'null'
          title: Slot
          description: >-
            The named slot on that step it answers. A step with one slot needs
            none, because there is nothing else it could be; a step with several
            needs it, and the workflow's `intake.slots` names them. A request
            that leaves it out where the step takes several is refused, naming
            the slots to choose from.
        kind:
          anyOf:
            - type: string
              minLength: 1
            - type: 'null'
          title: Kind
          description: >-
            Which of the slot's kinds this document is. The slot's `kinds` on
            the workflow's `intake.slots` names them: a slot naming several
            needs one of them here, and a slot naming one needs none, because
            there is nothing else the document could be.
        filename:
          type: string
          maxLength: 255
          minLength: 1
          title: Filename
          description: >-
            The file's name. It is kept on the record as the name this document
            was received under.
        content_type:
          type: string
          minLength: 1
          title: Content Type
          description: >-
            The file's MIME type, such as `image/jpeg` or `application/pdf`, as
            the step's slot accepts it.
        content:
          type: string
          minLength: 1
          title: Content
          description: The file itself, base64-encoded.
      additionalProperties: false
      type: object
      required:
        - step_key
        - filename
        - content_type
        - content
      title: CarriedDocument
      description: >-
        One document sent inside the request, and where in the workflow it
        belongs.
      examples:
        - content: /9j/4AAQSkZJRgABAQAAAQ...
          content_type: image/jpeg
          filename: pan-card.jpg
          step_key: pan
    WorkflowMode:
      type: string
      enum:
        - hosted
        - staged
        - instant
      title: WorkflowMode
      description: >-
        How a verification on this workflow is conducted, which every other rule
        about it follows from.
    VerificationStatus:
      type: string
      enum:
        - open
        - submitted
        - completed
        - cancelled
        - gated
        - expired
        - failed
      title: VerificationStatus
      description: Where a verification stands.
    ExpiryCause:
      type: string
      enum:
        - retention
        - client
      title: ExpiryCause
      description: What deleted a verification's data and closed the record for audit.
    AcknowledgementRecord:
      properties:
        submitted_at:
          type: string
          format: date-time
          title: Submitted At
          description: The submission this receipt answers.
        sent_at:
          type: string
          format: date-time
          title: Sent At
          description: When it was sent.
        message_id:
          type: string
          title: Message Id
          description: The identifier of the message that was sent, for tracing one send.
      type: object
      required:
        - submitted_at
        - sent_at
        - message_id
      title: AcknowledgementRecord
      description: The receipt telling the user their submission arrived.
    CallbackRecord:
      properties:
        status:
          $ref: '#/components/schemas/CallbackStatus'
          description: >-
            delivered once your endpoint accepted the callback; failed once
            every attempt at it was spent without one being accepted.
        settled_at:
          type: string
          format: date-time
          title: Settled At
          description: When the callback was accepted, or when the attempts ran out.
        reason:
          anyOf:
            - type: string
            - type: 'null'
          title: Reason
          description: >-
            Why no attempt was accepted, on a failed callback. Null on a
            delivered one.
      type: object
      required:
        - status
        - settled_at
        - reason
      title: CallbackRecord
      description: How the callback for this verification ended.
    ProgressRecord:
      properties:
        total:
          type: integer
          title: Total
          description: >-
            How many steps the workflow declares. Counted whichever steps the
            record reports, so on a journey that took one branch this is more
            than `steps` holds.
        passed:
          type: integer
          title: Passed
          description: Steps that were checked and passed.
        failed:
          type: integer
          title: Failed
          description: Steps that were checked and did not pass.
        awaiting:
          type: integer
          title: Awaiting
          description: Steps the user has not answered yet.
        enriching:
          type: integer
          title: Enriching
          description: Steps whose checks are still running.
        error:
          type: integer
          title: Error
          description: Steps where a check could not run.
        declined:
          type: integer
          title: Declined
          description: Steps the user chose not to provide.
        not_supplied:
          type: integer
          title: Not Supplied
          description: Steps the run closed over with nothing provided for them.
        undetermined:
          type: integer
          title: Undetermined
          description: >-
            Steps whose place in this journey is not settled yet, because
            whether they are asked for turns on something that has still to
            happen. These are reported in `steps`.
        not_applicable:
          type: integer
          title: Not Applicable
          description: >-
            Steps this journey ruled out, which the record leaves out of
            `steps`. Read the verification with `include_not_applicable` to see
            them.
      type: object
      required:
        - total
        - passed
        - failed
        - awaiting
        - enriching
        - error
        - declined
        - not_supplied
        - undetermined
        - not_applicable
      title: ProgressRecord
      description: >-
        Every step of the journey counted by where it stands; total equals the
        sum of the other fields.


        Counted over the whole journey, while `steps` reports only the part of
        it nothing has ruled out, so this is where a record says how much of the
        journey it is leaving out.
    StepRecord:
      properties:
        key:
          type: string
          title: Key
          description: The step's key within the workflow.
        title:
          anyOf:
            - type: string
            - type: 'null'
          title: Title
          description: >-
            The heading this step is presented under, in your workflow's own
            words. Null only where the workflow no longer declares the step,
            which a record read after its workflow changed can hold.
        label:
          anyOf:
            - type: string
            - type: 'null'
          title: Label
          description: >-
            Your own name for this step, where your workflow carries one.
            Several steps may share one, so a journey that asks a sole
            proprietor, a partner and a director each for a PAN reads the same
            name on whichever of them ran. Null where the workflow carries none;
            the `key` is what names this step everywhere.
        type:
          $ref: '#/components/schemas/StepType'
          description: The step's type.
        required:
          type: boolean
          title: Required
          description: Whether the journey cannot be submitted without this step.
        state:
          $ref: '#/components/schemas/StepState'
          description: >-
            Where the step stands. declined means the user chose not to provide
            it; not-supplied means the run closed with nothing provided for it,
            so it was closed over rather than left waiting; enriching means the
            step's checks are still running; error means a check could not run
            and will be retried; passed and failed are the outcomes of those
            checks; awaiting means the user has not answered it yet.


            undetermined means whether this journey asks for the step at all
            turns on something that has yet to happen, such as a value an
            earlier step will publish. It is not a step being waited on and not
            one ruled out: read it as a question the journey has not reached. It
            settles into one of the other states as the journey does, except
            where a verification ends with a check that never ran: the steps
            that turned on that check stay undetermined on the finished record.


            not-applicable means this journey did not ask for the step, because
            your workflow's rules ruled it out or because a value it reads was
            settled without being established. That is a conclusion rather than
            an open question, and the record leaves those steps out, so you only
            meet this state on one you read with `include_not_applicable`.
        reasons:
          items:
            $ref: '#/components/schemas/StepReason'
          type: array
          title: Reasons
          description: Why the step has not passed, when it has not.
        gaps:
          items:
            $ref: '#/components/schemas/StepReason'
          type: array
          title: Gaps
          description: >-
            What a passed step passed without: optional pieces it asked for that
            did not arrive. Empty unless the step passed.
        collected:
          anyOf:
            - $ref: '#/components/schemas/CollectedRecord'
            - type: 'null'
          description: What the step collected, once it was answered.
        documents:
          items:
            $ref: '#/components/schemas/DocumentRecord'
          type: array
          title: Documents
          description: The files this step holds, oldest first.
      type: object
      required:
        - key
        - title
        - label
        - type
        - required
        - state
        - reasons
        - gaps
        - collected
        - documents
      title: StepRecord
      description: One step of the workflow that this user was asked for.
    ErrorCode:
      type: string
      enum:
        - unauthenticated
        - client-not-enrolled
        - rate-limited
        - auth-unavailable
        - environment-mismatch
        - request-invalid
        - body-unreadable
        - page-cursor-invalid
        - window-invalid
        - request-too-large
        - not-found
        - method-not-allowed
        - internal-error
        - workflow-not-found
        - workflow-version-not-found
        - workflow-not-runnable
        - workflow-not-walkable
        - workflow-misconfigured
        - context-incomplete
        - context-value-invalid
        - mobile-required
        - journey-fields-refused
        - return-url-not-allowed
        - reference-taken
        - verification-not-found
        - verification-not-open
        - verification-expired
        - run-in-progress
        - credits-exhausted
        - resets-exhausted
        - live-limit-reached
        - step-not-found
        - step-not-ready
        - step-invalid
        - document-not-found
        - document-not-stored
        - document-too-large
        - document-type-not-allowed
      title: ErrorCode
      description: >-
        What went wrong, as a value to branch on.


        Published vocabulary, stated here rather than shared with any other
        product of ours: these are read by integrations we do not control, so a
        name here means what it says for as long as the endpoint answering it
        exists.


        One code names one cause, so a status carrying several causes is told
        apart by the code and never by the message. Codes are added as new
        causes become reachable; an integration therefore treats an unrecognised
        code as the status it arrived at.
    CallbackStatus:
      type: string
      enum:
        - delivered
        - failed
      title: CallbackStatus
      description: >-
        How the hand-off to the client ended. Absent while none has been
        attempted, or none is owed.
    StepType:
      type: string
      enum:
        - form
        - documents
        - parsed-documents
        - pan-card
        - bank-account
        - gst-certificate
        - digilocker
        - selfie
        - premises-photos
        - address-tagging
        - address-proof
        - udyam
        - pcb-certificate
        - name-match
        - gate-check
        - review
      title: StepType
      description: The sixteen step types. This list is closed.
    StepState:
      type: string
      enum:
        - not-applicable
        - undetermined
        - awaiting
        - enriching
        - error
        - passed
        - failed
        - declined
        - not-supplied
      title: StepState
      description: Where one step of a journey stands.
    StepReason:
      properties:
        code:
          type: string
          title: Code
          description: A stable identifier for the reason.
        message:
          type: string
          title: Message
          description: A readable explanation of the reason.
        details:
          additionalProperties: true
          type: object
          title: Details
          description: >-
            What the reason is about, as the values its message was written
            from. Keyed per code and not a fixed shape, so read a key you know
            and ignore the rest. A reason about one of a step's document slots
            carries that slot's key as `slot`, which is what attributes it to a
            single document rather than to the step as a whole.


            Empty on a record whose collected data has been cleared: the
            specifics go with the material, and only the code and the message
            are kept.
      type: object
      required:
        - code
        - message
      title: StepReason
      description: One machine-readable reason a step has not passed.
    CollectedRecord:
      properties:
        answer:
          additionalProperties: true
          type: object
          title: Answer
          description: >-
            The user's current answer, shaped per step type. A step whose answer
            is the files it gathered reports them as its documents rather than
            here, so this is empty on a step that asks for nothing else.
        outputs:
          additionalProperties: true
          type: object
          title: Outputs
          description: >-
            What the step's checks established. A step that passed publishes
            these for the steps after it to read, so a later check can be made
            against them.


            A step that failed reports what its checks found here as well, and
            nothing after it reads those. A cross-check that failed on one name
            still scored the others, and this is where those scores are.


            Where a step published its outputs, every field its type publishes
            is here, and one with nothing to say is null, so read those for a
            value rather than for the key. Two cases carry no key at all: a step
            that published nothing reports an empty object, and a form step
            publishes the fields your workflow declares, so one the user left
            blank is absent.


            Where your workflow is set up to reach you in names or shapes of
            your own, these keys are those names, and a field your workflow
            converts arrives as its expression yields it. Every other value
            keeps the place and the shape it is published in. This reference
            describes the fields as the system publishes them, so they are what
            to translate from, and `output_transformations` on the workflow
            states the translation. It reaches this object alone: `answer` comes
            back in the shape you send it.
      type: object
      required:
        - answer
        - outputs
      title: CollectedRecord
      description: What a step collected and what its checks established.
    DocumentRecord:
      properties:
        id:
          type: string
          format: uuid
          title: Id
          description: The document's id, used to download it.
        slot:
          type: string
          title: Slot
          description: The named slot the file sits in.
        kind:
          type: string
          title: Kind
          description: >-
            Which of its slot's kinds the file was provided as. Every slot names
            at least one, and `intake.slots` names them for every step answered
            over this API. A file a check fetched carries the kind of document
            the source returned, and a photo taken on the person's own screens
            carries the kind of photo it was asked for.
        label:
          anyOf:
            - type: string
            - type: 'null'
          title: Label
          description: >-
            That kind's name in your own system, where your workflow gives it
            one. The same label on the same document across branches is how you
            find it without knowing which branch ran.
        filename:
          type: string
          title: Filename
          description: The original filename.
        content_type:
          type: string
          title: Content Type
          description: The file's MIME type.
        size_bytes:
          type: integer
          title: Size Bytes
          description: The file's size in bytes.
        sha256:
          type: string
          title: Sha256
          description: The SHA-256 hash of the file's contents.
        received_at:
          type: string
          format: date-time
          title: Received At
          description: When the file was received.
      type: object
      required:
        - id
        - slot
        - kind
        - label
        - filename
        - content_type
        - size_bytes
        - sha256
        - received_at
      title: DocumentRecord
      description: >-
        One file on the record, whether the user uploaded it or the step fetched
        it on their behalf.
  securitySchemes:
    HTTPBearer:
      type: http
      scheme: bearer

````

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