Didit Workflows API

The Workflows API from Didit — 2 operation(s) for workflows.

OpenAPI Specification

didit-workflows-api-openapi.yml Raw ↑
openapi: 3.0.0
info:
  version: 3.0.0
  title: Didit Verification Billing Workflows API
  description: Identity verification API. Authenticate with x-api-key header.
servers:
- url: https://verification.didit.me
tags:
- name: Workflows
paths:
  /v3/workflows/:
    get:
      summary: List workflows
      description: List your workflows, newest first, in a limit/offset pagination envelope (`{count, next, previous, results}`, default page size 50). Each row is one version; `workflow_id` is the stable group ID and new sessions use the latest `published` version.
      operationId: list_workflows
      tags:
      - Workflows
      parameters:
      - name: limit
        in: query
        required: false
        schema:
          type: integer
          default: 50
        description: Page size (number of workflows per page).
      - name: offset
        in: query
        required: false
        schema:
          type: integer
          default: 0
        description: Number of rows to skip before the first returned workflow.
      responses:
        '200':
          description: One page of workflows ordered by `created_at` descending, wrapped in the pagination envelope. Each item in `results` is a `WorkflowListItem`.
          content:
            application/json:
              schema:
                type: object
                properties:
                  count:
                    type: integer
                    description: Total number of workflow versions for the application.
                  next:
                    type: string
                    format: uri
                    nullable: true
                    description: URL of the next page, or `null` on the last page.
                  previous:
                    type: string
                    format: uri
                    nullable: true
                    description: URL of the previous page, or `null` on the first page.
                  results:
                    type: array
                    items:
                      $ref: '#/components/schemas/WorkflowListItem'
              examples:
                Two workflows:
                  summary: A default KYC workflow and a draft KYC + AML workflow
                  value:
                    count: 2
                    next: null
                    previous: null
                    results:
                    - uuid: a1b2c3d4-5678-90ab-cdef-111111111111
                      workflow_id: a1b2c3d4-5678-90ab-cdef-111111111111
                      workflow_label: Standard KYC
                      workflow_type: kyc
                      is_default: true
                      is_archived: false
                      is_white_label_enabled: false
                      total_price: 0.15
                      min_price: 0.15
                      max_price: 0.15
                      features: OCR + LIVENESS + FACE_MATCH
                      is_simple_workflow: true
                      is_editable: false
                      workflow_url: https://verify.didit.me/u/_yljPOx8RWG3UAz5ZRQGVQ
                      max_retry_attempts: 3
                      retry_window_days: 7
                      session_expiration_time: 604800
                      version: 2
                      status: published
                      has_draft: false
                      created_by:
                        name: Alex Mateo
                        email: alex@example.com
                        type: user
                      updated_at: '2026-04-12T10:30:00Z'
                    - uuid: b2c3d4e5-6789-01bc-defa-222222222222
                      workflow_id: b2c3d4e5-6789-01bc-defa-222222222222
                      workflow_label: Full Verification + AML
                      workflow_type: kyc
                      is_default: false
                      is_archived: false
                      is_white_label_enabled: false
                      total_price: 0.25
                      min_price: 0.25
                      max_price: 0.25
                      features: OCR + LIVENESS + FACE_MATCH + AML
                      is_simple_workflow: true
                      is_editable: true
                      workflow_url: https://verify.didit.me/u/Aq3kPOx8RWG3UAz5ZRQGVQ
                      max_retry_attempts: 3
                      retry_window_days: 7
                      session_expiration_time: 604800
                      version: 1
                      status: draft
                      has_draft: true
                      created_by: null
                      updated_at: '2026-04-15T18:05:21Z'
        '403':
          description: 'The API key is missing, malformed, expired, or belongs to a different application. Body: `{"detail": "You do not have permission to perform this action."}`. Refresh the token via the [Auth API](/auth-api/get-credentials) and retry.'
          content:
            application/json:
              schema:
                type: object
                properties:
                  detail:
                    type: string
              examples:
                Invalid token:
                  value:
                    detail: You do not have permission to perform this action.
        '429':
          description: Rate limit exceeded. Retry with exponential backoff and honour any `Retry-After` header.
        '500':
          description: Unexpected server error while building the list. The request can be safely retried.
      security:
      - ApiKeyAuth: []
      x-codeSamples:
      - lang: curl
        label: cURL
        source: "curl -X GET 'https://verification.didit.me/v3/workflows/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Accept: application/json'"
      - lang: Python
        label: Python (requests)
        source: "import requests\n\nresp = requests.get(\n    \"https://verification.didit.me/v3/workflows/\",\n    headers={\"x-api-key\": \"YOUR_API_KEY\"},\n    timeout=10,\n)\nresp.raise_for_status()\npage = resp.json()\nfor workflow in page[\"results\"]:\n    print(workflow[\"uuid\"], workflow[\"workflow_label\"], workflow[\"status\"])"
      - lang: JavaScript
        label: Node.js (fetch)
        source: "const res = await fetch(\"https://verification.didit.me/v3/workflows/\", {\n  headers: { 'x-api-key': 'YOUR_API_KEY' },\n});\nif (!res.ok) throw new Error(`Didit ${res.status}`);\nconst page = await res.json();\npage.results.forEach((w) => console.log(w.uuid, w.workflow_label, w.status));"
    post:
      summary: Create workflow
      description: Create a simple workflow. Send `features` in execution order (ordering rules apply); defaults to `published` v1. The body accepts ONLY the fields listed in `SimpleWorkflowRequest` — any other key (including `workflow_type`) is rejected with a 400. Not idempotent — each call creates a new workflow. Maximum 50 workflows per application.
      operationId: create_workflow
      tags:
      - Workflows
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SimpleWorkflowRequest'
            examples:
              Simple KYC:
                summary: Linear ID, liveness, and face match workflow
                value:
                  workflow_label: Standard KYC
                  features:
                  - feature: OCR
                    config:
                      duplicated_user_action: review
                  - feature: LIVENESS
                    config:
                      face_liveness_method: passive
                  - feature: FACE_MATCH
                    config:
                      face_match_score_decline_threshold: 40
                      face_match_score_review_threshold: 60
              KYC + AML:
                summary: Run AML after ID verification
                value:
                  workflow_label: KYC with AML
                  features:
                  - feature: OCR
                  - feature: AML
                    config:
                      aml_score_review_threshold: 70
                      aml_score_approve_threshold: 30
              Questionnaire workflow:
                summary: Run a questionnaire created with POST /v3/questionnaires/
                value:
                  workflow_label: Source of Funds
                  features:
                  - feature: QUESTIONNAIRE
                    config:
                      questionnaire_uuid: 11111111-2222-3333-4444-555555555555
                      review_questionnaire_manually: true
      responses:
        '201':
          description: 'Workflow created. The response body is the FULL workflow configuration — the same raw `VerificationSettings` serialization returned by `GET /v3/workflows/{settings_uuid}/` (~190 fields: every feature toggle, threshold, action and the generated `workflow_graph`), not the compact list item. Store the `uuid` (also exposed as `workflow_id`) so you can reference it from later session-creation calls. Note: `features` is a `" + "`-joined string and prices are JSON numbers.'
          content:
            application/json:
              schema:
                type: object
                description: Full workflow configuration (abbreviated here — see `GET /v3/workflows/{settings_uuid}/`).
                additionalProperties: true
              examples:
                Created (abbreviated):
                  summary: Key fields of the full configuration object
                  value:
                    uuid: c3d4e5f6-7890-12cd-ef34-333333333333
                    workflow_id: c3d4e5f6-7890-12cd-ef34-333333333333
                    workflow_label: Standard KYC
                    workflow_type: null
                    is_default: false
                    is_archived: false
                    total_price: 0.15
                    min_price: 0.15
                    max_price: 0.15
                    features: OCR + LIVENESS + FACE_MATCH
                    is_simple_workflow: false
                    is_editable: false
                    workflow_url: https://verify.didit.me/u/w9TkPOx8RWG3UAz5ZRQGVQ
                    workflow_graph:
                      start_node: ocr
                      nodes: '... one node per feature plus a final status node ...'
                    max_retry_attempts: 3
                    retry_window_days: 7
                    session_expiration_time: 604800
                    version: 1
                    status: published
                    published_at: '2026-05-17T10:30:00Z'
                    created_at: '2026-05-17T10:30:00Z'
                    updated_at: '2026-05-17T10:30:00Z'
        '400':
          description: 'Validation error. Common causes: a top-level key outside the accepted whitelist (e.g. `workflow_type`), an unknown `feature` value, a feature placed before its dependency (e.g., `FACE_MATCH` before `OCR`), a passive feature (`AML`, `IP_ANALYSIS`, `DATABASE_VALIDATION`, `KYB_KEY_PEOPLE`) used as the first step, a `QUESTIONNAIRE` feature whose `config.questionnaire_uuid` does not exist for this application, or an out-of-range threshold. Body is a DRF validation error object — keys are field names, values are arrays of human-readable messages.'
          content:
            application/json:
              examples:
                Missing feature:
                  value:
                    features:
                    - At least one feature is required.
                Unknown top-level field:
                  value:
                    workflow_type:
                    - The v3 workflow API only accepts `workflow_label`, `is_default`, `status`, `features`, `is_white_label_enabled`, `is_desktop_allowed`, `max_retry_attempts`, `retry_window_days`, `session_expiration_time`, `face_liveness_max_attempts`, `face_match_max_attempts`.
                Unknown feature:
                  value:
                    features:
                    - 'Invalid feature ''FOO''. Allowed values: AGE_ESTIMATION, AML, DATABASE_VALIDATION, EMAIL_VERIFICATION, FACE_MATCH, IP_ANALYSIS, KYB_DOCUMENTS, KYB_KEY_PEOPLE, KYB_REGISTRY, LIVENESS, NFC, OCR, PHONE_VERIFICATION, PROOF_OF_ADDRESS, QUESTIONNAIRE.'
                Ordering:
                  value:
                    features:
                    - 'Feature ''FACE_MATCH'' must appear after one of: OCR.'
                Questionnaire not found:
                  value:
                    features: Questionnaire '11111111-2222-3333-4444-555555555555' was not found for this application. Create the questionnaire first, then use its questionnaire_id.
        '403':
          description: The API key is missing, malformed, expired, or scoped to a different application. Refresh via the [Auth API](/auth-api/get-credentials) and retry.
          content:
            application/json:
              examples:
                Invalid token:
                  value:
                    detail: You do not have permission to perform this action.
        '415':
          description: 'Unsupported media type. Set `Content-Type: application/json` and send a JSON body.'
        '429':
          description: Rate limit exceeded. Retry with exponential backoff.
        '500':
          description: Unexpected server error while creating the workflow. Safe to retry.
      security:
      - ApiKeyAuth: []
      x-codeSamples:
      - lang: curl
        label: cURL
        source: "curl -X POST 'https://verification.didit.me/v3/workflows/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n    \"workflow_label\": \"Standard KYC\",\n    \"features\": [\n      {\"feature\": \"OCR\"},\n      {\"feature\": \"LIVENESS\", \"config\": {\"face_liveness_method\": \"passive\"}},\n      {\"feature\": \"FACE_MATCH\", \"config\": {\"face_match_score_decline_threshold\": 40, \"face_match_score_review_threshold\": 60}}\n    ]\n  }'"
      - lang: Python
        label: Python (requests)
        source: "import requests\n\npayload = {\n    \"workflow_label\": \"Standard KYC\",\n    \"features\": [\n        {\"feature\": \"OCR\"},\n        {\"feature\": \"LIVENESS\", \"config\": {\"face_liveness_method\": \"passive\"}},\n        {\"feature\": \"FACE_MATCH\"},\n    ],\n}\nresp = requests.post(\n    \"https://verification.didit.me/v3/workflows/\",\n    headers={\"x-api-key\": \"YOUR_API_KEY\"},\n    json=payload,\n    timeout=10,\n)\nresp.raise_for_status()\nworkflow = resp.json()\nprint(\"Workflow id:\", workflow[\"uuid\"])"
      - lang: JavaScript
        label: Node.js (fetch)
        source: "const res = await fetch(\"https://verification.didit.me/v3/workflows/\", {\n  method: \"POST\",\n  headers: {\n    'x-api-key': 'YOUR_API_KEY',\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    workflow_label: \"Standard KYC\",\n    features: [\n      { feature: \"OCR\" },\n      { feature: \"LIVENESS\", config: { face_liveness_method: \"passive\" } },\n      { feature: \"FACE_MATCH\" },\n    ],\n  }),\n});\nif (!res.ok) throw new Error(`Didit ${res.status}: ${await res.text()}`);\nconst workflow = await res.json();\nconsole.log(\"Workflow id:\", workflow.uuid);"
  /v3/workflows/{settings_uuid}/:
    get:
      summary: Get workflow
      description: 'Fetch full configuration for one workflow version by `settings_uuid`: feature toggles, thresholds, allowed documents, graph, retry policy, callbacks, and pricing.'
      operationId: get_workflow
      tags:
      - Workflows
      parameters:
      - name: settings_uuid
        in: path
        required: true
        schema:
          type: string
          format: uuid
        description: Per-version UUID of the workflow (the `uuid` value returned by the list endpoint). Each version of a workflow has its own `settings_uuid`.
      responses:
        '200':
          description: 'Full workflow configuration. The shape is the raw `VerificationSettings` serialization (~190 fields: every feature toggle, threshold, warning action, allowed-documents config, the `workflow_graph`, retry policy, callbacks and pricing). The example below is abbreviated. Notes: `features` is a `" + "`-joined string (e.g. `"OCR + LIVENESS"`), prices are JSON numbers, and `is_editable` is `true` only for `draft` versions.'
          content:
            application/json:
              examples:
                KYC workflow with face match (abbreviated):
                  value:
                    uuid: a1b2c3d4-5678-90ab-cdef-111111111111
                    workflow_id: a1b2c3d4-5678-90ab-cdef-111111111111
                    workflow_label: Standard KYC
                    workflow_type: kyc
                    is_default: true
                    is_archived: false
                    is_liveness_enabled: true
                    face_liveness_method: passive
                    face_liveness_score_decline_threshold: 50
                    face_liveness_score_review_threshold: 70
                    is_face_match_enabled: true
                    face_match_score_decline_threshold: 40
                    face_match_score_review_threshold: 60
                    is_aml_enabled: false
                    is_phone_verification_enabled: false
                    is_email_verification_enabled: false
                    is_database_validation_enabled: false
                    is_ip_analysis_enabled: false
                    is_nfc_enabled: false
                    duplicated_user_action: no_action
                    documents_allowed:
                      ESP:
                        P:
                          sides: 1
                          enabled: 1
                          subtypes:
                          - EPASSPORT
                          - PASSPORT_GENERIC
                          preferred_characters: latin
                          expiration_check_mode: strict
                    max_retry_attempts: 3
                    retry_window_days: 7
                    session_expiration_time: 604800
                    version: 2
                    status: published
                    published_at: '2026-04-12T10:30:00Z'
                    is_simple_workflow: false
                    is_editable: false
                    workflow_url: https://verify.didit.me/u/_yljPOx8RWG3UAz5ZRQGVQ
                    total_price: 0.15
                    min_price: 0.15
                    max_price: 0.15
                    features: OCR + LIVENESS + FACE_MATCH
                    created_at: '2025-01-15T10:30:00Z'
                    updated_at: '2026-04-12T10:30:00Z'
        '403':
          description: API key is missing, malformed, expired, or scoped to a different application.
          content:
            application/json:
              examples:
                Invalid token:
                  value:
                    detail: You do not have permission to perform this action.
        '404':
          description: No workflow with this `settings_uuid` exists for the authenticated application. Either the UUID is wrong or it belongs to another application — Didit deliberately does not distinguish the two cases to avoid leaking the existence of cross-application records.
          content:
            application/json:
              examples:
                Not found:
                  value:
                    detail: Not found.
        '429':
          description: Rate limit exceeded. Retry with exponential backoff.
        '500':
          description: Unexpected server error. Safe to retry.
      security:
      - ApiKeyAuth: []
      x-codeSamples:
      - lang: curl
        label: cURL
        source: "curl -X GET 'https://verification.didit.me/v3/workflows/a1b2c3d4-5678-90ab-cdef-111111111111/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
      - lang: Python
        label: Python (requests)
        source: "import requests\n\nresp = requests.get(\n    f\"https://verification.didit.me/v3/workflows/{settings_uuid}/\",\n    headers={\"x-api-key\": \"YOUR_API_KEY\"},\n    timeout=10,\n)\nresp.raise_for_status()\nworkflow = resp.json()\nprint(workflow[\"workflow_label\"], workflow[\"status\"])"
      - lang: JavaScript
        label: Node.js (fetch)
        source: "const res = await fetch(`https://verification.didit.me/v3/workflows/${settingsUuid}/`, {\n  headers: { 'x-api-key': 'YOUR_API_KEY' },\n});\nif (!res.ok) throw new Error(`Didit ${res.status}`);\nconst workflow = await res.json();\nconsole.log(workflow.workflow_label, workflow.status);"
    patch:
      summary: Update workflow
      description: 'Update a workflow. Versioning depends on the `status` field you send and the current state of the version: (1) no `status` on a **published** version → the published version is updated in place (same `uuid`, same `version`); (2) no `status` on a **draft** → the draft is updated and immediately published; (3) `status: "published"` on a **published** version → a NEW published version is created under the same `workflow_id` (new `uuid`, `version` + 1) and returned, and any existing draft in the group is deleted; (4) `status: "draft"` keeps a draft as a draft (autosave) but is rejected with 400 on a published version (`"Cannot revert a published version to draft."`). The body accepts the same strict field whitelist as create — unknown keys are rejected with 400.'
      operationId: update_workflow
      tags:
      - Workflows
      parameters:
      - name: settings_uuid
        in: path
        required: true
        schema:
          type: string
          format: uuid
        description: Per-version UUID of the workflow to update.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SimpleWorkflowUpdateRequest'
            examples:
              Replace features:
                summary: Send the full desired feature order
                value:
                  features:
                  - feature: OCR
                  - feature: AML
              Rename:
                summary: Rename a workflow
                value:
                  workflow_label: Premium KYC
              Set as default:
                summary: Make this workflow the application's default
                value:
                  is_default: true
              Update config:
                summary: Change feature configuration
                value:
                  features:
                  - feature: OCR
                  - feature: LIVENESS
                    config:
                      face_liveness_method: passive
              Publish a draft:
                summary: Promote a draft to published
                value:
                  status: published
      responses:
        '200':
          description: 'Workflow updated. The body is the FULL configuration of the resulting version (same raw `VerificationSettings` shape as `GET /v3/workflows/{settings_uuid}/`). When the update created a new version (`status: "published"` sent on a published row) the returned `uuid` and `version` differ from the ones you patched — use the returned `uuid` for subsequent calls.'
          content:
            application/json:
              schema:
                type: object
                description: Full workflow configuration (see `GET /v3/workflows/{settings_uuid}/`).
                additionalProperties: true
        '400':
          description: 'Validation error — a top-level key outside the accepted whitelist, an unknown feature, invalid ordering, out-of-range threshold, referencing a non-existent questionnaire, or `status: "draft"` sent for a published version (`"Cannot revert a published version to draft."`). The response body is a DRF validation error keyed by field name.'
        '403':
          description: API key missing or invalid.
          content:
            application/json:
              examples:
                Invalid token:
                  value:
                    detail: You do not have permission to perform this action.
        '404':
          description: No workflow with this `settings_uuid` exists for the authenticated application.
        '415':
          description: 'Unsupported media type. Set `Content-Type: application/json`.'
        '429':
          description: Rate limit exceeded. Retry with exponential backoff.
        '500':
          description: Unexpected server error. Safe to retry.
      security:
      - ApiKeyAuth: []
      x-codeSamples:
      - lang: curl
        label: cURL
        source: "curl -X PATCH 'https://verification.didit.me/v3/workflows/a1b2c3d4-5678-90ab-cdef-111111111111/' \\\n  -H 'x-api-key: YOUR_API_KEY' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"workflow_label\": \"Premium KYC\"}'"
      - lang: Python
        label: Python (requests)
        source: "import requests\n\nresp = requests.patch(\n    f\"https://verification.didit.me/v3/workflows/{settings_uuid}/\",\n    headers={\"x-api-key\": \"YOUR_API_KEY\"},\n    json={\"workflow_label\": \"Premium KYC\"},\n    timeout=10,\n)\nresp.raise_for_status()\nprint(resp.json()[\"workflow_label\"])"
      - lang: JavaScript
        label: Node.js (fetch)
        source: "const res = await fetch(`https://verification.didit.me/v3/workflows/${settingsUuid}/`, {\n  method: \"PATCH\",\n  headers: {\n    'x-api-key': 'YOUR_API_KEY',\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({ workflow_label: \"Premium KYC\" }),\n});\nif (!res.ok) throw new Error(`Didit ${res.status}`);\nconst workflow = await res.json();\nconsole.log(workflow.workflow_label);"
    delete:
      summary: Delete workflow
      description: Permanently delete one workflow version (hard delete, no undo). Existing sessions keep their verification results but their workflow reference is cleared; other versions in the same `workflow_id` group are not deleted.
      operationId: delete_workflow
      tags:
      - Workflows
      parameters:
      - name: settings_uuid
        in: path
        required: true
        schema:
          type: string
          format: uuid
        description: Per-version UUID of the workflow to delete.
      responses:
        '204':
          description: Workflow deleted. The response body is empty.
        '403':
          description: API key missing or invalid.
          content:
            application/json:
              examples:
                Invalid token:
                  value:
                    detail: You do not have permission to perform this action.
        '404':
          description: No workflow with this `settings_uuid` exists for the authenticated application.
          content:
            application/json:
              examples:
                Not found:
                  value:
                    detail: Not found.
        '429':
          description: Rate limit exceeded. Retry with exponential backoff.
        '500':
          description: Unexpected server error. Safe to retry.
      security:
      - ApiKeyAuth: []
      x-codeSamples:
      - lang: curl
        label: cURL
        source: "curl -X DELETE 'https://verification.didit.me/v3/workflows/a1b2c3d4-5678-90ab-cdef-111111111111/' \\\n  -H 'x-api-key: YOUR_API_KEY'"
      - lang: Python
        label: Python (requests)
        source: "import requests\n\nresp = requests.delete(\n    f\"https://verification.didit.me/v3/workflows/{settings_uuid}/\",\n    headers={\"x-api-key\": \"YOUR_API_KEY\"},\n    timeout=10,\n)\nresp.raise_for_status()  # raises on 4xx/5xx; 204 is success"
      - lang: JavaScript
        label: Node.js (fetch)
        source: "const res = await fetch(`https://verification.didit.me/v3/workflows/${settingsUuid}/`, {\n  method: \"DELETE\",\n  headers: { 'x-api-key': 'YOUR_API_KEY' },\n});\nif (res.status !== 204) throw new Error(`Didit ${res.status}`);"
components:
  schemas:
    WorkflowListItem:
      type: object
      description: One workflow version in the list view.
      properties:
        uuid:
          type: string
          format: uuid
          description: Per-version UUID. Use as `{settings_uuid}` for get/update/delete, and as `workflow_id` when creating sessions.
        workflow_id:
          type: string
          format: uuid
          description: Stable group ID shared by every version of the same workflow. Equals `uuid` for version 1.
        workflow_label:
          type: string
          description: Display name for the workflow.
        workflow_type:
          type: string
          nullable: true
          description: 'Base type for simple workflows: `kyc`, `kyb`, `adaptive_age_verification`, `biometric_authentication`, etc. `null` for graph-based workflows without a KYB feature.'
        is_default:
          type: boolean
          description: Whether this is the default workflow for new sessions.
        is_archived:
          type: boolean
        is_white_label_enabled:
          type: boolean
          description: Whether white-label customization applies to sessions created with this workflow.
        total_price:
          type: number
          description: Fixed price per verification in USD (JSON number, excludes variable-priced features such as DATABASE_VALIDATION and PHONE_VERIFICATION).
        min_price:
          type: number
          description: Cheapest fixed price across workflow-graph paths, in USD.
        max_price:
          type: number
          description: Most expensive fixed price across workflow-graph paths, in USD.
        features:
          type: string
          description: Enabled features as a single `" + "`-joined string, e.g. `"OCR + LIVENESS + FACE_MATCH"`. Split on `" + "` to get a list.
        is_simple_workflow:
          type: boolean
          description: True when the workflow has no custom workflow graph.
        is_editable:
          type: boolean
          description: True when this version is a `draft` (drafts are editable in place; published versions are immutable in the Console).
        workflow_url:
          type: string
          format: uri
          description: Public shareable verification URL for this workflow (`https://verify.didit.me/u/<token>`).
        max_retry_attempts:
          type: integer
          description: Maximum retry attempts allowed after a declined verification (0-10).
        retry_window_days:
          type: integer
          nullable: true
          description: Rolling window in days used to count retries (1-365). `null` = all-time limit.
        session_expiration_time:
          type: integer
          description: Seconds before an unfinished session expires (3600-2419200).
        version:
          type: integer
          description: Version number within the `workflow_id` group, starting at 1.
        status:
          type: string
          enum:
          - draft
          - published
          description: Version status. New sessions use the latest `published` version of a group.
        has_draft:
          type: boolean
          description: True when any version in this `workflow_id` group is currently a draft.
        created_by:
          type: object
          nullable: true
          description: 'Who created this version: `{name, email, type}` where `type` is `user` (Console user, `email` set) or `api_key` (`name` is the client id, `email` is null). `null` when no creator was recorded.'
          properties:
            name:
              type: string
            email:
              type: string
              nullable: true
            type:
              type: string
              enum:
              - user
              - api_key
        updated_at:
          type: string
          format: date-time
    SimpleWorkflowRequest:
      type: object
      description: 'Create a simple linear workflow. The API converts this feature list into a node-based workflow graph internally. STRICT field whitelist: any key not listed here (including `workflow_type`) is rejected with a 400.'
      required:
      - features
      properties:
        workflow_label:
          type: string
          maxLength: 50
          default: ID Verification
          description: Display name for the workflow (max 50 characters). Defaults to `"ID Verification"` when omitted — always set it so workflows stay distinguishable.
          example: Standard KYC
        is_default:
          type: boolean
          description: Set this workflow as the default for new sessions.
        status:
          type: string
          enum:
          - draft
          - published
          description: Omit this field to create a published workflow ready for s

# --- truncated at 32 KB (38 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/didit/refs/heads/main/openapi/didit-workflows-api-openapi.yml