---
title: Human review
description: How a cascade pauses for a reviewer, what awaiting_review means for your integration, and the endpoints to claim, decide, note and audit reviews.
canonical_url: "https://cascades.crscreditapi.com/docs/concepts/human-review"
doc_version: "1.0.0"
last_updated: "2026-10-05T19:24:37Z"
source: docs/concepts/human-review.md
---

# Human review

An `IfElse` node can route an applicant to `human_review_steps` instead of passing or failing them outright — a borderline credit score, a record that needs a person's judgement. When that happens the execution stops at `status: awaiting_review` with `needs_human_review: true` and `review_status: in_review`. The nodes listed in the decision's `human_review_steps` run immediately (interim work such as a hold email or pre-generating an adverse-action draft); then the execution pauses, and neither `pass_steps` nor `fail_steps` runs until someone decides.

Reviewers can decide in the Cascades app; the API exposes the same actions so you can build the review queue into your own tooling.

## What happens at a decision?

`POST /executions/{id}/review_decisions` with `{ "decision": "approved" | "denied", "note": "…" }` records the decision and resumes the matching branch:

- **`approved`** resumes down the decision's `pass_steps`.
- **`denied`** resumes down the decision's `fail_steps`. An `AdverseAction` node placed in `human_review_steps` has already rendered its draft at flag time; the notice is sent when a reviewer sends it from the app, not by the decision itself (see [Adverse action](/docs/concepts/adverse-action)).

Test-mode executions resume inline: the response is `200 OK` with the final state and `resume_enqueued: false`. Live-mode executions enqueue the resume and answer `202 Accepted` with `resume_enqueued: true`; poll `GET /executions/{id}` until `status` leaves `awaiting_review` / `waiting`, or wait for the webhook.

If nobody has claimed the review, the decision claims it for the caller. Errors:

| Code | When |
|---|---|
| `409 review_not_pending` | The execution is not waiting for a review |
| `409 review_already_decided` | Someone already approved or denied it |
| `403 review_assigned_elsewhere` | The review is claimed by another user |
| `403 live_mode_forbidden` | Live execution, account without production access |

## Claiming and releasing

`POST /executions/{id}/review_assignment` with `{ "assignee": "me" }` claims the review for the user behind your key; `{ "assignee": null }` releases it. The body field is `assignee` (not `action`) because Rails reserves that parameter name. Each API client maps to a single user, so cross-user assignment is not a meaningful operation here — teams with several reviewers use one client per reviewer.

## Notes and the audit trail

- `POST /executions/{id}/review_notes` with `{ "note": "…" }` appends a `note_added` event (`201 Created`).
- `GET /executions/{id}/review_events` returns the full trail, oldest first: `flagged`, `assigned`, `unassigned`, `approved`, `denied`, `note_added`, `re_evaluated`, and the adverse-action notice events `adverse_action_drafted`, `adverse_action_sent`, `adverse_action_skipped` and `adverse_action_replayed`, each with the actor and timestamp. This is what you reconstruct "who decided what and when" from for compliance.

## Deciding many at once

`POST /executions/review_bulk_actions` applies `approve`, `deny` or `assign_to_me` to up to **25** execution ids in one request. It is always asynchronous (`202`) and returns `{ applied, enqueued, skipped }`, where `skipped` lists a reason per id that could not be processed: `not_awaiting_review`, `review_not_pending`, `assigned_elsewhere`, `live_mode_forbidden`, `already_assigned`, or `not_found`. Ids belonging to another tenant are reported as `not_found` so existence is never leaked.

## Finding what needs review

`GET /executions?filter[needs_human_review]=true&filter[review_status]=in_review` is your queue. Each row carries `assigned_to_user_id` so you can show who holds it.

## Related

- [Handle human review](/docs/guides/handle-human-review) — a worked integration
- [Executions](/docs/concepts/executions) — the status lifecycle
- [`POST /executions/{id}/review_decisions`](/docs/api/executions/submit-review-decision)

## Sitemap

See the full [sitemap](https://cascades.crscreditapi.com/sitemap.md) for all pages.
