Review (manual review)
The Review section of the admin console handles verification sessions routed to manual review. Reviewers inspect documents and applicant data, decide approval or rejection, and leave internal comments.
Integrators (server-to-server): the same queue is available on the Tenant API under
/tenant/v1/kyc/review-tasksand/tenant/v1/kyb/review-taskswith scopesreviews:*/kyb.reviews:*. See Review tasks (Tenant API).Admin console HTTP paths below are relative to the admin API (
/admin/v1/...), not the Tenant API.
Task queue
The queue lists tasks (sessions) waiting for manual review or in progress. Each task shows the session identifier, queue arrival date, current status, and the assigned reviewer.
Filters
To manage the queue, the following filters are available:
- By task status — new (waiting for assignment), in progress, approved, rejected.
- By assigned reviewer — tasks for a specific reviewer or unassigned tasks.
- By date — task arrival date range.
Queue statistics
The section header shows summary metrics:
- Number of tasks waiting for assignment.
- Number of tasks in progress.
- Total number of tasks processed in the current period.
Working on a task
When you open a task, you have access to the following information:
Session and applicant data
- Session and applicant identifier.
- Data extracted from the document (full name, date of birth, document number — when OCR is available).
- External user identifier (external_user_id).
Documents
- Uploaded document and selfie images, viewable at full size.
- Automated check results: document authenticity, image quality, face match.
Check history
- Chronological order of verification step execution.
- Automated check results (document check, liveness, face match, AML).
Reviewer actions
Task assignment
- Assign to me — the reviewer takes the task. The status changes to "In progress".
- Reassign — transfer the task to another reviewer (for example, when a reviewer with broader permissions is needed).
Decision
- Approve — verification passes. The session receives the
approvedstatus. - Reject — verification fails. The session receives the
rejectedstatus. On rejection, you must:- Pick a rejection reason from the structured list (
GET /admin/v1/review/reject-reasons), for exampleblurry_document,face_not_matching,suspected_fraud, orexpired_document. - Optionally enter an additional comment with an explanation.
- Pick a rejection reason from the structured list (
Canonical reject codes are the same as on the Tenant API (blurry_document, unreadable_document, face_not_matching, … — full list in Review tasks).
Changing task priority
Through PATCH /admin/v1/review/tasks/{task_id}/priority, a reviewer with the right permission can change the task priority (for example, urgent VIP cases). The action is logged as review.priority_updated.
Delegating a task
Through POST /admin/v1/review/tasks/{task_id}/delegate, a reviewer can delegate the task to the KnowaKYC manual-review team. The current delegation status is returned by GET /admin/v1/review/tasks/{task_id}/delegation-status.
Comments
Reviewers can add an internal comment through POST /admin/v1/review/tasks/{task_id}/comments. Comments are visible to other reviewers and stored in the task history for audit and context handover.
Accessing uploaded documents
To view a specific applicant document, use GET /admin/v1/review/tasks/{task_id}/documents/{document_id}/url — it returns a signed URL with a limited lifetime.
Queue statistics
Aggregate review-task metrics (queue size, in progress, processed for a period) are available through GET /admin/v1/review/stats (or GET /admin/v1/review/queue with scope kyc / kyb).
Resubmit requests
Sometimes automated checks pass, but during manual review a document field turns out to be unreadable (glare, blur, cropped frame, wrong document, expired, etc.). In that case you can ask the user to resubmit a specific step without rejecting the whole session. This preserves conversion and saves the user from running through verification from scratch.
Use case
- The reviewer opens a task in the review queue and sees that the front-side document photo is blurry.
- Instead of rejecting, the reviewer clicks "Request resubmit", picks the step (for example,
document_capture) and the reason code (blurry). - The session moves to awaiting_resubmit, and the selected step is reset.
- The user receives a notification and reopens the flow — they go straight to the reset step with the reason explained.
- After successful resubmission, the session returns to the review queue automatically.
Reason codes (reason_code)
The allowed reason codes are:
| Code | Description |
|---|---|
illegible | Text is unreadable |
blurry | Image is blurred |
cropped | Document is cropped |
glare | Glare obscures the data |
wrong_document | Wrong document type uploaded |
expired_document | Document has expired |
partial | Document is not fully captured |
The same codes are used in webhook payloads and in the message shown to the user.
Limits and TTL
- Up to 3 requests per session by default. A fourth attempt returns
409 Conflictwith codeconflict. - After the supporting backend version and schema are deployed, an approved database change can set
flow_review_tasks.resubmit_limit_overrideto 4–10 for one task. Record that change in the operations audit trail.NULLkeeps the default. Existing resubmit rows remain intact; the limit counts all requests regardless of status. - TTL — 7 days. After that, the request transitions to
expired, and the session closes with the final statusrejected(if no other channel completed it). - No more than one active request per (session, step) pair at a time. A duplicate attempt returns
409 Conflictwith coderesubmit_already_pending. - The session must be active for review resubmit.
in_progresssessions are accepted. A completed session can also be accepted when it is in the manual-review/resubmit path; the backend reopens it and resets the selected step atomically. Requests against pending, paused, failed, cancelled, or expired sessions return409 Conflictwith codesession_not_in_progress. - Only applicant-actionable step types can be resubmitted. The current allowlist is
document,selfie,phone_otp,email_otp,kyb_company_input,kyb_business_document, andkyb_beneficiary_kyc.
Endpoints
Create a resubmit request
POST /admin/v1/review/tasks/{task_id}/request-resubmit
Content-Type: application/json
{
"step_id": "550e8400-e29b-41d4-a716-446655440000",
"reason_code": "blurry",
"client_message": "Please re-take the document in daylight without glare",
"internal_notes": "Date of birth field is unreadable due to glare"
}step_id— UUID of the specific flow step to reset.reason_code— required, from the canonical list above.client_message(optional) — text shown to the user.internal_notes(optional) — internal note for other reviewers; not shown to the user.
Response (200 OK):
{
"data": {
"request_id": "550e8400-e29b-41d4-a716-446655440099",
"task_id": "550e8400-e29b-41d4-a716-446655440010",
"status": "pending",
"reason_code": "blurry",
"expires_at": "2026-05-04T10:00:00Z"
}
}The action is logged in the audit trail (review.decided + decision=request_resubmit + reason_code).
List task resubmit requests
GET /admin/v1/review/tasks/{task_id}/resubmitsReturns every resubmit request for the task (including fulfilled / expired / cancelled), sorted by creation date.
Request lifecycle
| Status | Description |
|---|---|
pending | Request created, sent to the user, waiting for resubmission |
fulfilled | The user resubmitted the step — the task is back in the review queue |
expired | 7 days passed without resubmission — the session closes with rejection |
cancelled | Request cancelled by the admin / tenant before fulfilment |
The pending → fulfilled transition happens automatically after the user completes the requested step again.
User notification delivery
KnowaKYC delivers the resubmit notification through the available user channels:
- WebSocket push — instant, when the user has the verification flow open.
- Email / SMS — sent when the user needs a session-resume link outside the open verification page.
Webhook events
When a request is created or fulfilled, KnowaKYC sends webhook events:
verification.resubmit_requested— a reviewer requested resubmission. The payload includessession_id,flow_id,applicant_id,step_id,step_type,reason_code,client_message,attempt_number,requested_by_id,requested_by_name,expires_at.verification.resubmit_fulfilled— the user resubmitted. The payload includessession_id,flow_id,applicant_id,step_id,reason_code,attempt_number,fulfilled_at.
Full payload schemas are in Webhooks API.
Outcome of processing
After a decision is made:
- The session receives a final status (
approvedorrejected). - The result is available through the Tenant API and is sent to configured webhooks (events
verification.approved/verification.declined). - The decision, rejection reason, and comments are recorded in the audit log.
Review comment webhooks
New comments on KYC review tasks emit verification.comment.created; new comments on KYB review tasks emit kyb.review.comment.created. Comments created in the tenant dashboard, the platform review console, and the tenant API use the same contract. These events do not change the verification decision or complete the session.
Subscribe to the exact event type for the required scope. Existing * subscriptions also receive these events. Delivery uses the existing webhook signature, environment filtering, retries, and delivery logs. Events are delivered at least once; consumers must deduplicate using the event id or idempotency_key. Arrival order is not guaranteed.
Example event data for KYC:
{
"scope": "kyc",
"task_id": "550e8400-e29b-41d4-a716-446655440010",
"session_id": "550e8400-e29b-41d4-a716-446655440001",
"flow_id": "550e8400-e29b-41d4-a716-446655440002",
"external_id": "customer_123",
"applicant_id": "550e8400-e29b-41d4-a716-446655440099",
"comment": {
"id": "550e8400-e29b-41d4-a716-446655440011",
"content": "Please provide a clearer document photo.",
"created_at": "2026-10-16T08:00:00.123456Z",
"author_type": "admin_user"
}
}For KYB, scope is kyb and business_id replaces applicant_id when present. Author types are admin_user, superadmin_user, api_key, and system. Employee identifiers and names are not included in the webhook. All task comments are client-visible; decision internal_notes and resubmission client_message are separate fields and do not produce comment events. Only newly created comments generate these events; existing comments are not replayed.
Retrieve comments with GET /tenant/v1/kyc/review-tasks/{task_id}/comments (reviews:read) or GET /tenant/v1/kyb/review-tasks/{task_id}/comments (kyb.reviews:read). Creating a comment uses POST at the same path and the corresponding write scope. The successful creation response adds comment_id and created_at, matching the saved comment and webhook snapshot. Each successful POST creates a new comment; webhook event deduplication does not make repeated creation requests idempotent. After an uncertain request outcome, reconcile using the comments API before resubmitting.
The comment, webhook event, and outbox entry are committed together. Failure to persist the event rolls back comment creation. HTTP delivery happens asynchronously after commit, so a successful comment response is not proof of successful HTTP webhook delivery; use delivery logs.