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

# Add reviewer to case

> Add a reviewer to a case. The reviewer receives a notification and their
status is set to `Invited` until they begin their review.




## OpenAPI

````yaml /zenoo-api-openapi.yaml post /v1/cases/{case_token}/reviewers
openapi: 3.1.0
info:
  title: Zenoo API
  version: 3.0.0
  summary: >-
    Unified compliance platform API — orchestration, case management, and
    screening
  description: >
    > **Welcome to the Zenoo API v3**

    >

    > Zenoo is a unified compliance platform that combines verification
    orchestration

    > (Studio) with case management (CLM) through a single API surface. Submit
    entity

    > data, run checks, manage investigations, and track compliance decisions —
    all

    > through one integration.


    ## Platform Architecture


    ```

    Your System ──► Zenoo API v3
                       │
                       ├── Studio (Orchestration)
                       │     ├── Flow execution (sync / async)
                       │     ├── Provider routing (WorldCheck, Sumsub, ComplyAdvantage)
                       │     └── Structured results with risk scoring
                       │
                       └── CLM (Case Management)
                             ├── Case lifecycle (create → investigate → close)
                             ├── Alert triage (auto-priority, SLA tracking)
                             ├── Risk assessment (4-dimension scoring)
                             ├── Audit trail (immutable compliance log)
                             └── AI-powered research and disposition
    ```


    ## Key Concepts


    | Concept | Description | Token Prefix |

    |---------|-------------|--------------|

    | **Flow** | Orchestration template that defines which checks to run |
    `flw_` |

    | **Case** | Investigation container — groups entities, alerts, and checks |
    `cas_` |

    | **Entity** | Person or company under investigation | `ent_` |

    | **Alert** | Issue requiring analyst review (PEP match, sanctions hit,
    etc.) | `alt_` |

    | **Check** | Verification action (screening, identity, document, company) |
    `chk_` |

    | **Risk Assessment** | 4-dimension risk score with tiered classification |
    `rsk_` |

    | **Comment** | Analyst note, decision record, or system event on a case |
    `cmt_` |

    | **Audit Log** | Immutable record of every action taken on the platform |
    `aud_` |


    ## Authentication


    All requests require authentication via one of two methods:


    | Method | Header | Use Case |

    |--------|--------|----------|

    | **API Key** | `X-API-KEY: <your-key>` | Server-to-server integrations |

    | **OAuth 2.0** | `Authorization: Bearer <token>` | Application-level access
    with scoped permissions |


    API keys are project-scoped. Staging and production use different keys.

    Never expose API keys in client-side code.


    ## Pagination


    All list endpoints use cursor-based pagination:


    ```json

    {
      "data": [...],
      "meta": {
        "cursor": "eyJpZCI6ImNhc18xMjM0In0=",
        "has_more": true
      }
    }

    ```


    Pass the `cursor` value as a query parameter to fetch the next page.

    Default page size is 25; maximum is 100.


    ## Idempotency


    All mutation endpoints (POST, PATCH, DELETE) support the `Idempotency-Key`
    header.

    Send the same key within 24 hours to safely retry requests without duplicate
    side effects.


    ## Rate Limits


    | Plan | Requests/min | Burst |

    |------|-------------|-------|

    | Starter | 60 | 10 |

    | Professional | 300 | 50 |

    | Enterprise | 1000 | 200 |


    Rate limit headers are included in every response:

    `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`.


    ## Versioning


    This API follows semantic versioning. The current version is **v3.0.0**.

    Breaking changes are communicated via email and changelog at least 30 days
    in advance.
  contact:
    name: Zenoo Developer Support
    email: support@zenoo.com
    url: https://zenoo.com
  license:
    name: Proprietary
    url: https://zenoo.com/terms
servers:
  - url: https://instance.prod.onboardapp.io
    description: Production (replace "instance" with your subdomain)
  - url: https://instance.staging.onboardapp.io
    description: Staging (replace "instance" with your subdomain)
  - url: https://api.zenoo.com
    description: Case Management API
security:
  - ApiKeyAuth: []
tags:
  - name: Flow API
    description: >
      Submit entity data for compliance verification — company registry lookups,
      person

      identity checks, and AML screening. The Flow API supports three flow

      types, each available in synchronous and asynchronous modes.


      ## Flow Types


      | Type | Endpoint Pattern | Description |

      |------|-----------------|-------------|

      | **Company** | `/api/gateway/execute/{project_hash}/api` (sync) |
      Registry lookup + director/UBO screening |

      | **Company** | `/api/gateway/execute/{project_hash}/init` (async) | Same
      checks, returns tokens immediately |

      | **Person** | `/api/gateway/execute/{project_hash}/kyc/api` (sync) |
      Identity + screening (server-side) |

      | **Person** | `/api/gateway/execute/{project_hash}/kyc/init` (async) |
      Identity + document capture + biometrics |

      | **Screening** | `/api/gateway/execute/{project_hash}/screening/api` |
      Standalone PEP/sanctions/adverse media check |

      | **Results** | `GET /api/gateway/sharable-payload/{pull_token}` |
      Retrieve async verification results |


      ## Capabilities


      | Capability | Description |

      |-----------|-------------|

      | **Sync execution** | Block until all checks complete (with configurable
      timeout via `X-SYNC-TIMEOUT`) |

      | **Async execution** | Initiate verification, retrieve results via pull
      token or webhook |

      | **Multi-provider** | Route checks across WorldCheck, Sumsub,
      ComplyAdvantage, and more |

      | **Idempotency** | Use `external_reference` to prevent duplicate
      verifications |

      | **Verification URLs** | Generate hosted verification journeys for
      document capture + biometrics |


      ## Execution Models


      ```

      Sync:   POST /api (or /kyc/api) ──► Checks Run ──► Full Results Returned
      (200)
                                       └──► Timeout ──► Partial Results + Tokens (202)

      Async:  POST /init (or /kyc/init) ──► Tokens Returned (200)
                                            ├──► GET /sharable-payload/{pull} ──► Results
                                            └──► Webhook delivery (recommended)
      ```


      > **Use sync** for server-to-server checks (screening, registry lookups)
      where you need results immediately.

      > **Use async** for client-facing journeys (document capture, biometric
      liveness) or when processing may exceed timeout.
  - name: Entities
    description: >
      Manage person and company entities under compliance investigation.
      Entities are

      the subjects of verification — they belong to cases, receive checks, and
      generate

      alerts when screening matches are found.


      ## Capabilities


      | Capability | Description |

      |-----------|-------------|

      | **Create** | Register a person or company entity with identifying data |

      | **Update** | Patch entity attributes as new information becomes
      available |

      | **List checks** | View all verification checks associated with an entity
      |

      | **List alerts** | View all alerts generated from entity screening
      results |


      ## Entity Types


      | Type | Key Fields | Typical Checks |

      |------|-----------|----------------|

      | **Person** | first_name, last_name, date_of_birth, nationality |
      Identity, Screening, Document |

      | **Company** | company_name, registration_number, country | Company
      registry, Corporate screening |


      ## Entity Roles


      | Role | Description |

      |------|-------------|

      | `Primary` | The main subject of the case |

      | `UBO` | Ultimate Beneficial Owner (>=25% ownership) |

      | `Director` | Company director or officer |

      | `Shareholder` | Company shareholder below UBO threshold |
  - name: Cases
    description: >
      Manage the full lifecycle of compliance investigation cases. A case groups
      entities,

      alerts, checks, risk assessments, and audit trails into a single
      investigation unit.


      ## Capabilities


      | Capability | Description |

      |-----------|-------------|

      | **Lifecycle management** | Create, update, close, escalate cases |

      | **Entity management** | Add persons and companies to a case |

      | **Alert aggregation** | View all alerts across case entities |

      | **Risk assessment** | Calculate and manage 4-dimension risk scores |

      | **Collaboration** | Comments, reviewers, and compliance reports |

      | **Audit trail** | Immutable timeline of all case actions |


      ## Case Lifecycle


      ```

      New ──► In Progress ──► In Review ──► Closed
        │         │               │
        │         ├──► Client Input ──┘
        │         │
        │         └──► Internal Review ──┘
        │
        └──► Escalated
      ```


      ## Case Types


      | Type | Description | Typical Duration |

      |------|-------------|-----------------|

      | `Onboarding` | New customer due diligence | 1-5 business days |

      | `Review` | Periodic review of existing customer | 5-15 business days |

      | `Perpetual` | Ongoing monitoring case (no fixed end) | Continuous |
  - name: Alerts
    description: >
      Triage, investigate, and resolve compliance alerts. Alerts are generated
      automatically

      when screening checks find matches (PEP, sanctions, adverse media) or when
      verification

      checks fail. Each alert requires analyst review and resolution.


      ## Capabilities


      | Capability | Description |

      |-----------|-------------|

      | **Triage** | Acknowledge, assign, and prioritize alerts |

      | **Resolution** | Resolve as true positive, false positive, or escalate |

      | **Bulk operations** | Resolve, acknowledge, or assign multiple alerts at
      once |

      | **AI research** | Trigger AI-powered research for deeper investigation |

      | **SLA tracking** | Automatic priority scoring and deadline management |


      ## Alert Lifecycle


      ```

      Open ──► Acknowledged ──► Resolved
        │           │              │
        │           │         (False Positive)
        │           │
        └──► Escalated
      ```


      ## Alert Categories


      | Category | Source | Typical Priority |

      |----------|--------|-----------------|

      | `PEP Match` | Screening provider | High |

      | `Sanctions Hit` | Screening provider | Critical |

      | `Adverse Media` | Screening provider | Medium-High |

      | `Name Mismatch` | Identity check | Medium |

      | `DOB Mismatch` | Identity check | Medium |

      | `Watchlist Match` | Screening provider | High |

      | `API Failure` | System | Low |
  - name: Checks
    description: >
      Execute and manage verification checks on entities. Checks are the atomic
      units

      of verification — each check runs against a specific provider and produces
      a

      pass/fail/refer result.


      ## Capabilities


      | Capability | Description |

      |-----------|-------------|

      | **Execute** | Trigger a check to run against its configured provider |

      | **Waive** | Mark a check as waived with a documented reason |

      | **Reuse** | Automatically reuse valid results from prior checks |

      | **Status tracking** | Monitor check progress through its lifecycle |


      ## Check Categories


      | Category | Examples | Typical Providers |

      |----------|---------|-------------------|

      | `Identity` | Document OCR, biometric liveness, face match | Sumsub |

      | `Screening` | PEP, sanctions, adverse media, watchlist | WorldCheck,
      ComplyAdvantage |

      | `Company` | Registry lookup, corporate structure | Registry providers |

      | `Financial` | Source of funds, transaction monitoring | Financial data
      providers |

      | `EDD` | Enhanced due diligence, deep research | AI services |


      ## Check Lifecycle


      ```

      Pending ──► Queued ──► In Progress ──► Complete (Pass/Fail/Refer)
                                  │
                                  ├──► Awaiting Document
                                  ├──► Awaiting Client
                                  ├──► Failed
                                  ├──► Retry Scheduled
                                  └──► Cancelled
      ```
  - name: Risk Assessments
    description: >
      Manage risk assessments that score entities across four dimensions. Risk
      assessments

      produce an overall score and tier classification (High/Medium/Low) used
      for

      due diligence path routing and SLA assignment.


      ## Capabilities


      | Capability | Description |

      |-----------|-------------|

      | **Calculate** | Run the risk model against case data to produce a score
      |

      | **Approve** | Senior reviewer approves the assessment |

      | **Override** | Override the calculated tier with justification |


      ## Risk Dimensions


      | Dimension | Weight | Factors |

      |-----------|--------|---------|

      | `customer` | 30% | Entity type, PEP status, sanctions, adverse media |

      | `geographic` | 25% | Country risk, FATF status, jurisdiction |

      | `product_service` | 25% | Product complexity, regulatory exposure |

      | `transaction` | 20% | Volume, frequency, unusual patterns |


      ## Risk Tiers


      | Tier | Score Range | Due Diligence Path | Review Frequency |

      |------|------------|-------------------|-----------------|

      | `High` | 70-100 | EDD (Enhanced) | 6 months |

      | `Medium` | 40-69 | CDD (Standard) | 12 months |

      | `Low` | 0-39 | SDD (Simplified) | 24-36 months |
  - name: Audit Trail
    description: >
      Access the immutable audit log that records every action taken on the
      platform.

      Audit logs are append-only and cannot be modified or deleted, ensuring
      full

      regulatory compliance and traceability.


      ## Capabilities


      | Capability | Description |

      |-----------|-------------|

      | **Query** | Filter logs by event type, actor, target, and date range |

      | **Case timeline** | View the complete history of a specific case |

      | **Compliance export** | Generate audit reports for regulatory
      submissions |


      ## Event Types


      | Category | Events |

      |----------|--------|

      | **Case** | case.created, case.status_changed, case.closed,
      case.escalated |

      | **Alert** | alert.created, alert.acknowledged, alert.resolved,
      alert.escalated |

      | **Check** | check.executed, check.completed, check.failed, check.waived
      |

      | **Risk** | risk_assessment.calculated, risk_assessment.approved,
      risk_assessment.overridden |

      | **Entity** | entity.created, entity.updated, entity.added_to_case |
  - name: Analytics
    description: >
      Access compliance metrics and statistics for dashboards, reporting, and
      operational

      monitoring. Analytics endpoints provide aggregated data across cases,
      alerts,

      and checks.


      ## Capabilities


      | Capability | Description |

      |-----------|-------------|

      | **Summary metrics** | Key compliance KPIs (open cases, pending alerts,
      SLA health) |

      | **Alert statistics** | Alert volume, resolution rates, category
      breakdown |

      | **Case statistics** | Case throughput, aging, type distribution |
  - name: Webhooks
    description: >
      Register and manage webhook endpoints to receive real-time notifications
      when

      events occur on the platform. Webhook payloads are signed with HMAC-SHA256

      for verification.


      ## Events


      | Event | Trigger | Typical Latency |

      |-------|---------|----------------|

      | `case.created` | New case is created | <5 seconds |

      | `case.status_changed` | Case status transitions | <5 seconds |

      | `case.closed` | Case is closed | <5 seconds |

      | `case.escalated` | Case is escalated | <5 seconds |

      | `alert.created` | New alert is generated | <5 seconds |

      | `alert.resolved` | Alert is resolved | <5 seconds |

      | `alert.escalated` | Alert is escalated | <5 seconds |

      | `check.completed` | Check finishes successfully | <5 seconds |

      | `check.failed` | Check fails after retries | After last retry |

      | `risk_assessment.completed` | Risk score calculated | <5 seconds |

      | `risk_assessment.approved` | Assessment approved | <5 seconds |

      | `sla.warning` | SLA deadline approaching | At warning threshold |

      | `sla.breached` | SLA deadline passed | At breach time |


      ## Signature Verification


      Every webhook includes an `X-Zenoo-Signature` header containing `sha256=`
      followed

      by the hex-encoded HMAC-SHA256 digest of the raw request body, computed
      with your

      webhook secret.


      **Verify signatures using constant-time comparison:**


      | Language | Function |

      |----------|----------|

      | Node.js | `crypto.timingSafeEqual()` |

      | Python | `hmac.compare_digest()` |

      | Java | `MessageDigest.isEqual()` |

      | Go | `hmac.Equal()` |


      ## Retry Schedule


      | Attempt | Delay |

      |---------|-------|

      | 1st retry | 1 minute |

      | 2nd retry | 5 minutes |

      | 3rd retry | 30 minutes |

      | 4th retry | 1 hour |

      | 5th-168th | Every 1 hour for 7 days |


      After 7 days of consecutive failures, the webhook is marked as
      undeliverable.
  - name: Comments
    description: >
      Manage discussion and collaboration on cases. Comments support analyst
      notes,

      formal decisions, system-generated events, and user mentions for team
      coordination.


      ## Comment Types


      | Type | Description | Created By |

      |------|-------------|-----------|

      | `Comment` | Free-form analyst note or observation | Analyst |

      | `Decision` | Formal decision record (approve, decline, escalate) |
      Senior reviewer |

      | `Note` | Internal note not visible to external parties | Any user |

      | `System` | Auto-generated event record (status change, assignment) |
      System |
paths:
  /v1/cases/{case_token}/reviewers:
    post:
      tags:
        - Cases
      summary: Add reviewer to case
      description: |
        Add a reviewer to a case. The reviewer receives a notification and their
        status is set to `Invited` until they begin their review.
      operationId: addCaseReviewer
      parameters:
        - name: case_token
          in: path
          required: true
          description: Case token.
          schema:
            type: string
        - $ref: '#/components/parameters/IdempotencyKeyHeader'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                user_id:
                  type: string
                  description: User ID of the reviewer to add.
                role:
                  type: string
                  enum:
                    - Approver
                  description: Reviewer role.
                  default: Approver
              required:
                - user_id
      responses:
        '201':
          description: Reviewer added.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/ApiResponse'
                  - type: object
                    properties:
                      data:
                        $ref: '#/components/schemas/Reviewer'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalError'
components:
  parameters:
    IdempotencyKeyHeader:
      name: Idempotency-Key
      in: header
      description: >
        Unique key for idempotent request handling. If a request with the same
        key

        was already processed within the last 24 hours, the original response is
        returned.
      schema:
        type: string
        format: uuid
  schemas:
    ApiResponse:
      type: object
      description: |
        Standard response wrapper for all API endpoints. Contains the resource
        data and pagination metadata.
      properties:
        data:
          description: Response payload. Type varies by endpoint.
        meta:
          type: object
          properties:
            request_id:
              type: string
              description: Unique request identifier for debugging and support.
              example: req_9k4m2n1p3q
            page:
              type: object
              description: Pagination metadata (present on list endpoints).
              properties:
                cursor:
                  type: string
                  nullable: true
                  description: Cursor for fetching the next page. Null if no more pages.
                has_more:
                  type: boolean
                  description: Whether more results are available.
    Reviewer:
      type: object
      description: A reviewer assigned to a case for approval or oversight.
      properties:
        token:
          type: string
          description: Unique reviewer assignment identifier.
        user_id:
          type: string
          description: User ID of the reviewer.
        name:
          type: string
          description: Reviewer display name.
        role:
          type: string
          enum:
            - Approver
          description: Reviewer role within the case.
        status:
          type: string
          enum:
            - Invited
            - Reviewing
            - Approved
            - Declined
          description: |
            Current review status.
            - `Invited` — Reviewer has been invited but has not started
            - `Reviewing` — Reviewer is actively reviewing
            - `Approved` — Reviewer approved the case
            - `Declined` — Reviewer declined/rejected the case
        notes:
          type: string
          nullable: true
          description: Reviewer notes or comments.
        invited_at:
          type: string
          format: date-time
        responded_at:
          type: string
          format: date-time
          nullable: true
    ErrorResponse:
      type: object
      description: >
        Standard error response. All errors include a machine-readable `code`,

        human-readable `message`, and a `request_id` for support
        troubleshooting.
      properties:
        error:
          type: object
          required:
            - code
            - message
            - request_id
          properties:
            code:
              type: string
              description: >
                Machine-readable error code. Use this for programmatic error
                handling.


                | Code | HTTP | Description | Retry? |

                |------|------|-------------|--------|

                | `VALIDATION_ERROR` | 400 | Malformed request body or
                parameters | No |

                | `INVALID_JSON` | 400 | Request body is not valid JSON | No |

                | `UNAUTHORIZED` | 401 | Invalid or missing API key | No |

                | `FORBIDDEN` | 403 | Insufficient permissions | No |

                | `NOT_FOUND` | 404 | Resource does not exist | No |

                | `TOKEN_EXPIRED` | 404 | Pull or start token has expired | No |

                | `RATE_LIMITED` | 429 | Rate limit exceeded | Yes (after reset)
                |

                | `INTERNAL_ERROR` | 500 | Unexpected server error | Yes (with
                backoff) |

                | `PROVIDER_ERROR` | 502 | External provider failure | Yes (with
                backoff) |

                | `SERVICE_UNAVAILABLE` | 503 | Service temporarily unavailable
                | Yes (with backoff) |
              enum:
                - VALIDATION_ERROR
                - INVALID_JSON
                - UNAUTHORIZED
                - FORBIDDEN
                - NOT_FOUND
                - TOKEN_EXPIRED
                - RATE_LIMITED
                - INTERNAL_ERROR
                - PROVIDER_ERROR
                - SERVICE_UNAVAILABLE
            message:
              type: string
              description: Human-readable error description.
            details:
              type: array
              description: Field-level validation errors (present for `validation_error`).
              items:
                type: object
                properties:
                  field:
                    type: string
                    description: JSON path to the invalid field.
                  message:
                    type: string
                    description: Description of the validation failure.
                  code:
                    type: string
                    description: >-
                      Field-level error code (e.g., `required`,
                      `invalid_format`).
            request_id:
              type: string
              description: >
                Unique request identifier. Include this when contacting Zenoo
                support

                for faster issue resolution.
              example: req_9k4m2n1p3q
  responses:
    BadRequest:
      description: >-
        Invalid request — check the error details for field-level validation
        errors.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    Unauthorized:
      description: Missing or invalid authentication credentials.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    NotFound:
      description: The requested resource does not exist. Verify the token is correct.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    UnprocessableEntity:
      description: >-
        Request is well-formed but cannot be processed due to business logic
        constraints.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    TooManyRequests:
      description: >-
        Rate limit exceeded. Retry after the time indicated in the
        `X-RateLimit-Reset` header.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
      headers:
        X-RateLimit-Limit:
          $ref: '#/components/headers/X-RateLimit-Limit'
        X-RateLimit-Remaining:
          $ref: '#/components/headers/X-RateLimit-Remaining'
        X-RateLimit-Reset:
          $ref: '#/components/headers/X-RateLimit-Reset'
    InternalError:
      description: >-
        Unexpected server error. Include the `request_id` from the error
        response when contacting support.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
  headers:
    X-RateLimit-Limit:
      description: Maximum requests allowed per minute for your plan.
      schema:
        type: integer
    X-RateLimit-Remaining:
      description: Requests remaining in the current rate limit window.
      schema:
        type: integer
    X-RateLimit-Reset:
      description: Unix timestamp when the rate limit window resets.
      schema:
        type: integer
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-KEY
      description: |
        Project-scoped API key for server-to-server authentication.
        Obtain keys from the Zenoo dashboard under Project Settings > API Keys.
        Staging and production environments use separate keys.

````