API reference

Cases

Escalate an alert into a case, investigate it, and send it for a second person to decide.

These endpoints need a signed-in person, not an API key. See roles for who can do what: anyone signed in can read cases, analysts, reviewers and admins can work them, and only reviewers and admins can decide one.

A case groups the alerts, entities and notes behind one investigation, and ends in an STR or in being closed without one. It is identified by a reference such as CASE-0192.

StatusMeaning
investigatingBeing worked. The narrative, alerts, entities and notes can change.
pending_reviewSent for review. Waiting for a second person.
closedDecided: reported to the FIC, or closed without a report.

Open a case

POST /v1/cases

Escalates an alert into a new case. The alert moves to in_review and is assigned to the caller. It is safe to repeat: a second call for the same alert returns the case it is already in, with 200 instead of 201.

Terminal
curl -X POST "$SENTINEL_URL/v1/cases" \
  -H "Authorization: Bearer $SENTINEL_SESSION" \
  -H "Content-Type: application/json" \
  -d '{"alert_id": "1f570324-fd0f-49ac-a66f-30829a86b841"}'

List cases

GET /v1/cases

Most recently active first, a page at a time. Filter with status (investigating, pending_review or closed) or assignee (a user id). Page with limit (1 to 200, default 50) and cursor, which is the next_cursor of the previous page. The last page has no next_cursor.

GET /v1/cases/counts returns how many cases are in each status, for tabs.

Work a case

Method and pathWhat it does
GET /v1/cases/{id}The case, with its alerts, entities and narrative
PATCH /v1/cases/{id}Edit the narrative (up to 20,000 characters) while the case is investigating
POST /v1/cases/{id}/alertsAdd an alert by alert_id. A closed case, or an alert already in another open case, is a 409.
POST /v1/cases/{id}/entitiesAdd an entity by entity_id, with a role such as subject or linked
POST /v1/cases/{id}/notesAdd a note (body, up to 4,000 characters) to the trail
POST /v1/cases/{id}/narrative/regenerateRedraft the narrative from the case's alerts and the rules that fired
GET /v1/cases/{id}/activityWhat happened on the case, newest first

Send for review and decide

POST /v1/cases/{id}/submit

Sends the case for review and sets it to pending_review. The person who sends it can't decide it.

GET /v1/cases/{id}/review

What the reviewer is asked to decide, and what changed since they last looked. Opening it moves the caller's mark forward, so the next call shows only what is new.

POST /v1/cases/{id}/review/decision

A reviewer or admin who is not the submitter decides:

Request
{
  "verdict": "approve",
  "comment": "Grounds are clear and the MTN letter is attached.",
  "checks": ["grounds", "kyc", "attachments", "conflict"]
}
verdictWhat happens
approveNeeds all four checks. The case closes as reported and its STR is sent to goAML. Returns 202.
send_backBack to investigating, with the comment on the trail. Returns 200.
rejectCloses the case without a report. Returns 200.

After an approval, the receipt appears on the case once the FIC answers. If goAML refuses the STR, the case goes back to pending_review with str.error set. If goAML can't be reached, the filing is retried every 5 minutes. See Reports.

Sentinel is a Somu Labs product. © 2026 Somu Labs Ltd.