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

# Record a manual decision (dashboard)

> Compliance officer's final verdict on a KYB case — the dashboard "Decision" tab. Mirrors the KYC (docver) manual set-status. The verdict is signed (the reviewer's account id + time), becomes the case's stored `status`, and is appended to the case's append-only decision journal (see GET .../decisions).

`verdict` is **approved** or **rejected** — same vocabulary as the status, so the frontend uses one enum for the current status and the action. A decision writes the `_manually` variant: approved → approved_manually, rejected → rejected_manually (so a reviewer-set status is obvious). The officer may override the automatic risk-driven outcome, e.g. approve a high-risk case. `remediation_requested` is NOT settable here — it is stamped automatically when a remediation ticket is created.

`comment` is **mandatory** for every decision (the audit trail requires a justification); a blank comment is a 400.

Auth: web session, Admin role in the organization (same gate as the KYC set-status). Tenancy from the path — a case in another org returns 404.



## OpenAPI

````yaml https://api.dataspike.io/openapi/kyb/public.json post /webapi/v4/kyb/organization/{organizationId}/verifications/{caseId}/decision
openapi: 3.1.0
info:
  description: Know Your Business (KYB) — case creation and the embedded onboarding widget.
  title: Dataspike KYB API
  version: '1.0'
servers: []
security: []
paths:
  /webapi/v4/kyb/organization/{organizationId}/verifications/{caseId}/decision:
    post:
      tags:
        - KYB Verifications
      summary: Record a manual decision (dashboard)
      description: >-
        Compliance officer's final verdict on a KYB case — the dashboard
        "Decision" tab. Mirrors the KYC (docver) manual set-status. The verdict
        is signed (the reviewer's account id + time), becomes the case's stored
        `status`, and is appended to the case's append-only decision journal
        (see GET .../decisions).


        `verdict` is **approved** or **rejected** — same vocabulary as the
        status, so the frontend uses one enum for the current status and the
        action. A decision writes the `_manually` variant: approved →
        approved_manually, rejected → rejected_manually (so a reviewer-set
        status is obvious). The officer may override the automatic risk-driven
        outcome, e.g. approve a high-risk case. `remediation_requested` is NOT
        settable here — it is stamped automatically when a remediation ticket is
        created.


        `comment` is **mandatory** for every decision (the audit trail requires
        a justification); a blank comment is a 400.


        Auth: web session, Admin role in the organization (same gate as the KYC
        set-status). Tenancy from the path — a case in another org returns 404.
      operationId: >-
        POST_/webapi/v4/kyb/organization/:organizationId/verifications/:caseId/decision
      parameters:
        - description: Organization id.
          in: path
          name: organizationId
          required: true
          schema:
            type: string
        - description: KYB case id (the `id` from the list).
          in: path
          name: caseId
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DecisionRequest'
          application/xml:
            schema:
              $ref: '#/components/schemas/DecisionRequest'
        description: Request body for kyb.DecisionRequest
        required: true
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: d5293a33-1d10-4aa2-8ff9-4a2c9a2d1e19
            application/xml:
              schema:
                $ref: d5293a33-1d10-4aa2-8ff9-4a2c9a2d1e19
          description: OK
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrInvalidVerdict'
            application/xml:
              schema:
                $ref: '#/components/schemas/ErrInvalidVerdict'
          description: verdict is not approved|rejected, or the comment is missing.
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrCaseNotFound'
            application/xml:
              schema:
                $ref: '#/components/schemas/ErrCaseNotFound'
          description: Case not found.
        '409':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrCaseNotSubmitted'
            application/xml:
              schema:
                $ref: '#/components/schemas/ErrCaseNotSubmitted'
          description: >-
            `case_not_submitted` when the case is still a draft (nothing has
            been submitted to decide on), and `request_open` when an information
            request is still with the applicant — cancel the round first, or
            wait for the answer. A case that already carries a decision IS
            decidable: an officer may revise their own verdict.
        default:
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DecisionResponse'
            application/xml:
              schema:
                $ref: '#/components/schemas/DecisionResponse'
          description: Decision recorded; case resolved.
      security:
        - Session: []
components:
  schemas:
    DecisionRequest:
      description: DecisionRequest schema
      properties:
        comment:
          example: >-
            UBO documents verified against the registry; approving despite the
            medium risk score.
          type: string
        verdict:
          example: approved
          type: string
      type: object
    ErrInvalidVerdict:
      description: ErrInvalidVerdict schema
      example:
        code: invalid_verdict
        message: verdict must be "approved" or "rejected"
        param: verdict
      properties:
        code:
          example: email_otp_expired
          type: string
        message:
          example: OTP has expired
          type: string
        param:
          nullable: true
          type: string
      type: object
    ErrCaseNotFound:
      description: ErrCaseNotFound schema
      example:
        code: case_not_found
        message: Case not found
      properties:
        code:
          example: email_otp_expired
          type: string
        message:
          example: OTP has expired
          type: string
        param:
          nullable: true
          type: string
      type: object
    ErrCaseNotSubmitted:
      description: ErrCaseNotSubmitted schema
      example:
        code: case_not_submitted
        message: Case has not been submitted yet
      properties:
        code:
          example: email_otp_expired
          type: string
        message:
          example: OTP has expired
          type: string
        param:
          nullable: true
          type: string
      type: object
    DecisionResponse:
      description: DecisionResponse schema
      example:
        id: 019f179b-0fa7-72c8-818e-819652540477
        status: approved_manually
        status_source: manual
        decided_by: a0f2c1d4e5b6a7c8
        decided_at: '0001-01-01T00:00:00Z'
      properties:
        decided_at:
          format: date-time
          type: string
        decided_by:
          example: a0f2c1d4e5b6a7c8
          type: string
        id:
          example: 019f179b-0fa7-72c8-818e-819652540477
          type: string
        status:
          example: approved_manually
          type: string
        status_source:
          example: manual
          type: string
      type: object
  securitySchemes:
    Session:
      description: Session cookie for web dashboard authentication.
      in: cookie
      name: ds-prod-session
      type: apiKey

````