Skip to Content
API referenceReview Events

Review events

Review events tell your systems that review work started, moved, or finished. They’re delivered to the webhook endpoints you set up in Settings → Integrations → Webhook delivery. For setup, verification, retries, and signing, see Webhooks.

The same catalog is published as an AsyncAPI 3 document  you can load into your own tooling.

Review events report what happened. Don’t resume paused work because of one: your application gets its outcome through the signed outcome callback. Nothing your endpoint sends back records a decision. Reviewers decide in VeriProof.

Event fields

Every review event has the same fields, in camelCase JSON. A field with no value is sent as null.

FieldTypeWhat it holds
idstringThe event ID, such as evt_7c1d…. Retries and resends keep it, and it matches the webhook-id header.
typestringOne of the review event types.
schemaVersionintegerThe payload version. It’s 1 today.
timestringWhen the change happened, as an ISO 8601 timestamp.
tenantIdstringYour VeriProof organization.
applicationIdstringThe application that asked for review.
sessionIdstringThe session the review belongs to.
reviewCaseIdstringThe review case.
caseVersionintegerThe case version after this change.
eventSequenceintegerThis event’s position among the case’s events. It only goes up.
decisionstring or nullThe outcome, once there is one: approved, rejected, follow_up_required, response_submitted, cancelled, or expired. Reviewer comments are never included.
reviewTierstringstandard, high, or urgent.
dueAtstringWhen the review is due.
expiresAtstringWhen the review expires if no one decides.
reasonCategorystringA short fixed reason. See Reason categories.
presentationDigeststring or nullSHA-256 (hex) of what the assigned reviewer is shown. null until the case has an assignment.
caseUrlstringThe application API URL for the case, …/v1/review-cases/{reviewCaseId}. Read it with an application key.

Events don’t include prompts, model output, tool payloads, reviewer comments, or personal data. When your integration needs more, read caseUrl with an application key that’s allowed to see it. You always get the case as it is now, never a stale copy from an old event.

Review event types

Choose any of these for an endpoint.

TypeSent whendecision
review.case.createdA policy result opens a review case.null
review.case.assignment_changedThe case is claimed or moves to a different reviewer.null
review.case.follow_up_requiredThe reviewer asks for more information before deciding.follow_up_required
review.case.decidedThe reviewer records a decision.approved, rejected, or response_submitted
review.case.cancelledThe case is cancelled before a decision.cancelled
review.case.expiredThe case reaches expiresAt without a decision.expired
review.case.overdueThe case passes dueAt and is still open.The current value, usually null
review.continuation.acknowledgedYour application reports what it did with the outcome.The case’s decision
review.continuation.delivery_failedVeriProof gives up sending the outcome callback to your application.The case’s decision

The examples below follow one case from start to finish, then show the other ways a case can end.

review.case.created

A new case, not yet assigned. reasonCategory says why review was needed.

{ "id": "evt_4f9a2c7e1b0d8a35c6e2f14b9d07a8c3e5f1b2d4", "type": "review.case.created", "schemaVersion": 1, "time": "2026-09-30T14:02:11.482+00:00", "tenantId": "3f2b8c1e-7d4a-4e9b-9c61-2a5d0e8f7b13", "applicationId": "9d6e1a47-2c3b-4f58-a0e9-7b1c5d2f8e60", "sessionId": "c2a7f0d9-4e1b-4c36-8d5a-0f9e3b6a1c72", "reviewCaseId": "71b3e5d2-8a0c-4f6e-9b14-2d7c0a5e3f98", "caseVersion": 1, "eventSequence": 1, "decision": null, "reviewTier": "high", "dueAt": "2026-09-30T18:02:11.482+00:00", "expiresAt": "2026-10-01T14:02:11.482+00:00", "reasonCategory": "high_risk_action", "presentationDigest": null, "caseUrl": "https://ingest.veriproof.app/v1/review-cases/71b3e5d2-8a0c-4f6e-9b14-2d7c0a5e3f98" }

review.case.assignment_changed

A reviewer claimed the case, or it moved to someone else. reasonCategory is claimed or reassigned. If you own reviewer notification, this is your cue to notify the new reviewer.

{ "id": "evt_0b8e3d61a7c24f95e1d0b3a6c8f27e4d19a5c0b7", "type": "review.case.assignment_changed", "schemaVersion": 1, "time": "2026-09-30T14:05:40.117+00:00", "tenantId": "3f2b8c1e-7d4a-4e9b-9c61-2a5d0e8f7b13", "applicationId": "9d6e1a47-2c3b-4f58-a0e9-7b1c5d2f8e60", "sessionId": "c2a7f0d9-4e1b-4c36-8d5a-0f9e3b6a1c72", "reviewCaseId": "71b3e5d2-8a0c-4f6e-9b14-2d7c0a5e3f98", "caseVersion": 2, "eventSequence": 2, "decision": null, "reviewTier": "high", "dueAt": "2026-09-30T18:02:11.482+00:00", "expiresAt": "2026-10-01T14:02:11.482+00:00", "reasonCategory": "claimed", "presentationDigest": "5d41c0a2e9b7f3186a4c2d9e0f7b1a3c8e6d5f4b2a1c0e9d8f7a6b5c4d3e2f1a", "caseUrl": "https://ingest.veriproof.app/v1/review-cases/71b3e5d2-8a0c-4f6e-9b14-2d7c0a5e3f98" }

review.case.overdue

The due time passed and the case is still open. reasonCategory is overdue.

{ "id": "evt_e27c9a0f4b1d6385a2e7c0f9b4d1a6e3c8f0b2d5", "type": "review.case.overdue", "schemaVersion": 1, "time": "2026-09-30T18:02:30.004+00:00", "tenantId": "3f2b8c1e-7d4a-4e9b-9c61-2a5d0e8f7b13", "applicationId": "9d6e1a47-2c3b-4f58-a0e9-7b1c5d2f8e60", "sessionId": "c2a7f0d9-4e1b-4c36-8d5a-0f9e3b6a1c72", "reviewCaseId": "71b3e5d2-8a0c-4f6e-9b14-2d7c0a5e3f98", "caseVersion": 2, "eventSequence": 3, "decision": null, "reviewTier": "high", "dueAt": "2026-09-30T18:02:11.482+00:00", "expiresAt": "2026-10-01T14:02:11.482+00:00", "reasonCategory": "overdue", "presentationDigest": "5d41c0a2e9b7f3186a4c2d9e0f7b1a3c8e6d5f4b2a1c0e9d8f7a6b5c4d3e2f1a", "caseUrl": "https://ingest.veriproof.app/v1/review-cases/71b3e5d2-8a0c-4f6e-9b14-2d7c0a5e3f98" }

review.case.follow_up_required

The reviewer needs more information before deciding. The case stays open.

{ "id": "evt_9c4b7e2a0d5f1836c9e4b7a2d0f5c1e8a3b6d9f2", "type": "review.case.follow_up_required", "schemaVersion": 1, "time": "2026-09-30T18:20:05.390+00:00", "tenantId": "3f2b8c1e-7d4a-4e9b-9c61-2a5d0e8f7b13", "applicationId": "9d6e1a47-2c3b-4f58-a0e9-7b1c5d2f8e60", "sessionId": "c2a7f0d9-4e1b-4c36-8d5a-0f9e3b6a1c72", "reviewCaseId": "71b3e5d2-8a0c-4f6e-9b14-2d7c0a5e3f98", "caseVersion": 3, "eventSequence": 4, "decision": "follow_up_required", "reviewTier": "high", "dueAt": "2026-09-30T18:02:11.482+00:00", "expiresAt": "2026-10-01T14:02:11.482+00:00", "reasonCategory": "high_risk_action", "presentationDigest": "5d41c0a2e9b7f3186a4c2d9e0f7b1a3c8e6d5f4b2a1c0e9d8f7a6b5c4d3e2f1a", "caseUrl": "https://ingest.veriproof.app/v1/review-cases/71b3e5d2-8a0c-4f6e-9b14-2d7c0a5e3f98" }

review.case.decided

The reviewer recorded a decision in VeriProof. Your application gets the outcome through its outcome callback, not through this event.

{ "id": "evt_3a6d9f0c2e5b8147a3d6f9c0e2b5a8d1f4c7e0b3", "type": "review.case.decided", "schemaVersion": 1, "time": "2026-09-30T19:11:52.761+00:00", "tenantId": "3f2b8c1e-7d4a-4e9b-9c61-2a5d0e8f7b13", "applicationId": "9d6e1a47-2c3b-4f58-a0e9-7b1c5d2f8e60", "sessionId": "c2a7f0d9-4e1b-4c36-8d5a-0f9e3b6a1c72", "reviewCaseId": "71b3e5d2-8a0c-4f6e-9b14-2d7c0a5e3f98", "caseVersion": 4, "eventSequence": 5, "decision": "approved", "reviewTier": "high", "dueAt": "2026-09-30T18:02:11.482+00:00", "expiresAt": "2026-10-01T14:02:11.482+00:00", "reasonCategory": "high_risk_action", "presentationDigest": "5d41c0a2e9b7f3186a4c2d9e0f7b1a3c8e6d5f4b2a1c0e9d8f7a6b5c4d3e2f1a", "caseUrl": "https://ingest.veriproof.app/v1/review-cases/71b3e5d2-8a0c-4f6e-9b14-2d7c0a5e3f98" }

review.continuation.acknowledged

Your application told VeriProof what it did with the outcome. reasonCategory is what happened: resumed, terminated, remained_paused, superseded, or failed.

{ "id": "evt_d8f1b4a7c0e3962d8f1b4a7c0e3d6a9f2c5e8b1d", "type": "review.continuation.acknowledged", "schemaVersion": 1, "time": "2026-09-30T19:12:03.208+00:00", "tenantId": "3f2b8c1e-7d4a-4e9b-9c61-2a5d0e8f7b13", "applicationId": "9d6e1a47-2c3b-4f58-a0e9-7b1c5d2f8e60", "sessionId": "c2a7f0d9-4e1b-4c36-8d5a-0f9e3b6a1c72", "reviewCaseId": "71b3e5d2-8a0c-4f6e-9b14-2d7c0a5e3f98", "caseVersion": 5, "eventSequence": 7, "decision": "approved", "reviewTier": "high", "dueAt": "2026-09-30T18:02:11.482+00:00", "expiresAt": "2026-10-01T14:02:11.482+00:00", "reasonCategory": "resumed", "presentationDigest": "5d41c0a2e9b7f3186a4c2d9e0f7b1a3c8e6d5f4b2a1c0e9d8f7a6b5c4d3e2f1a", "caseUrl": "https://ingest.veriproof.app/v1/review-cases/71b3e5d2-8a0c-4f6e-9b14-2d7c0a5e3f98" }

Sequence numbers can skip. VeriProof records steps that don’t produce a public event, such as the callback receipt between these two events.

review.continuation.delivery_failed

VeriProof couldn’t deliver the outcome callback to your application and stopped trying. Repair the callback endpoint, then replay the delivery from the case. See Operate application callbacks.

{ "id": "evt_6b0e3c9f2a5d8174b0e3c9f2a5d8e1b4c7f0a3d6", "type": "review.continuation.delivery_failed", "schemaVersion": 1, "time": "2026-10-03T19:12:00.915+00:00", "tenantId": "3f2b8c1e-7d4a-4e9b-9c61-2a5d0e8f7b13", "applicationId": "9d6e1a47-2c3b-4f58-a0e9-7b1c5d2f8e60", "sessionId": "5e8a1d3c-0b7f-4a29-9c6e-3f1d8b2a7e05", "reviewCaseId": "0e4c8b2a-6d1f-4935-a7c0-9b3e5d1f7a24", "caseVersion": 4, "eventSequence": 6, "decision": "rejected", "reviewTier": "standard", "dueAt": "2026-09-30T22:40:00.000+00:00", "expiresAt": "2026-10-01T18:40:00.000+00:00", "reasonCategory": "callback_delivery_failed", "presentationDigest": "a9c3e1f7b5d2084c6e1a9f3b7d5c2e0a8f6b4d1c9e7a5f3b1d0c8e6a4f2b9d7c", "caseUrl": "https://ingest.veriproof.app/v1/review-cases/0e4c8b2a-6d1f-4935-a7c0-9b3e5d1f7a24" }

review.case.cancelled

The case was cancelled before anyone decided, for example because the person using your application backed out. reasonCategory says why.

{ "id": "evt_f5a8c1e4b7d0293f5a8c1e4b7d0a3c6f9e2b5d8a", "type": "review.case.cancelled", "schemaVersion": 1, "time": "2026-09-30T15:47:18.530+00:00", "tenantId": "3f2b8c1e-7d4a-4e9b-9c61-2a5d0e8f7b13", "applicationId": "9d6e1a47-2c3b-4f58-a0e9-7b1c5d2f8e60", "sessionId": "8f2d6a0c-3e9b-4d17-b5a8-1c7e4f0a9d36", "reviewCaseId": "2c9a5e1d-7f3b-4082-86d4-a0e7c3b9f512", "caseVersion": 3, "eventSequence": 3, "decision": "cancelled", "reviewTier": "standard", "dueAt": "2026-09-30T19:30:00.000+00:00", "expiresAt": "2026-10-01T15:30:00.000+00:00", "reasonCategory": "end_user_cancelled", "presentationDigest": "c7e5a3f1d9b8062e4c7a5f3d1b9e8c6a4f2d0b7e5c3a1f9d8b6e4c2a0f7d5b3e", "caseUrl": "https://ingest.veriproof.app/v1/review-cases/2c9a5e1d-7f3b-4082-86d4-a0e7c3b9f512" }

review.case.expired

No one decided before expiresAt. An expired case never counts as approval.

{ "id": "evt_1c4f7a0d3b6e9258c1f4a7d0b3e6c9f2a5d8b1e4", "type": "review.case.expired", "schemaVersion": 1, "time": "2026-10-01T09:00:00.212+00:00", "tenantId": "3f2b8c1e-7d4a-4e9b-9c61-2a5d0e8f7b13", "applicationId": "9d6e1a47-2c3b-4f58-a0e9-7b1c5d2f8e60", "sessionId": "b4e0a7c3-1d9f-4658-8e2b-6a3c0f9d5e71", "reviewCaseId": "e8d2b6f0-4a1c-4739-9e5b-3c7a1f8d0b46", "caseVersion": 3, "eventSequence": 4, "decision": "expired", "reviewTier": "urgent", "dueAt": "2026-10-01T08:00:00.000+00:00", "expiresAt": "2026-10-01T09:00:00.000+00:00", "reasonCategory": "expired", "presentationDigest": "e1b9d7f5c3a2186e0b9d7f5c3a1e8b6d4f2c0a9e7b5d3f1c8a6e4b2d0f9c7a5e", "caseUrl": "https://ingest.veriproof.app/v1/review-cases/e8d2b6f0-4a1c-4739-9e5b-3c7a1f8d0b46" }

Reason categories

reasonCategory is always one of these values. Treat a value you don’t recognize as other.

GroupValues
Why review was neededpolicy_requires_human_review, high_risk_action, sensitive_data
Who has the caseclaimed, reassigned
Why the case was cancelledend_user_cancelled, parent_workflow_ended, safer_alternative_completed, checkpoint_unavailable, checkpoint_superseded, application_lifecycle, policy_rule_withdrawn
Timeoverdue, expired
What your application didresumed, terminated, remained_paused, superseded, failed
Outcome callbackcallback_delivery_failed
Anything elseother

Subscription events

Every endpoint receives these events about the subscription itself. You can’t turn them off, and they go out even while the endpoint isn’t receiving review events. They share id, type, schemaVersion, time, and tenantId with review events, and add subscriptionId plus the fields below.

TypeSent whenExtra fields
subscription.verification_requestedThe endpoint is created, its URL or signing method changes, it’s turned back on after VeriProof turned it off, or someone sends verification again.challenge
subscription.disabledAn event kept failing for three days and VeriProof turned the endpoint off.reason
subscription.signing_key_rotatingSomeone rotated the endpoint’s whsec_ secret. The old secret keeps signing for 24 hours.previousSecretValidUntil
subscription.events_missedThe endpoint starts receiving again after being off.missedFrom, missedUntil

reason is endpoint_gone or retries_exhausted. In practice you’ll see retries_exhausted: after a 410 Gone, VeriProof sends nothing more to that endpoint.

Answer subscription.verification_requested with a 2xx status and {"challenge": "<the same value>"}, as shown in Webhooks.

{ "id": "evt_0192a3f5d8e07b1c9a2d4e6f8b0c1d3e", "type": "subscription.disabled", "schemaVersion": 1, "time": "2026-10-04T02:15:09.644+00:00", "tenantId": "3f2b8c1e-7d4a-4e9b-9c61-2a5d0e8f7b13", "subscriptionId": "a41c7e92-5b3d-4f08-8e6a-1d9c2b7f0e54", "reason": "retries_exhausted" }
{ "id": "evt_0192a3f6a1b27c3d8e4f5a6b7c8d9e0f", "type": "subscription.signing_key_rotating", "schemaVersion": 1, "time": "2026-10-05T10:00:00.000+00:00", "tenantId": "3f2b8c1e-7d4a-4e9b-9c61-2a5d0e8f7b13", "subscriptionId": "a41c7e92-5b3d-4f08-8e6a-1d9c2b7f0e54", "previousSecretValidUntil": "2026-10-06T10:00:00.000+00:00" }
{ "id": "evt_0192a3f7b2c38d4e9f5a6b7c8d9e0f1a", "type": "subscription.events_missed", "schemaVersion": 1, "time": "2026-10-04T16:40:27.318+00:00", "tenantId": "3f2b8c1e-7d4a-4e9b-9c61-2a5d0e8f7b13", "subscriptionId": "a41c7e92-5b3d-4f08-8e6a-1d9c2b7f0e54", "missedFrom": "2026-10-04T02:15:09.644+00:00", "missedUntil": "2026-10-04T16:40:27.318+00:00" }

Handle events safely

Delivery is at least once, with no ordering guarantee. A receiver that follows these rules stays correct when events repeat or arrive late:

  1. Verify the signature before reading the body. See Verify a request.
  2. Store the event under its id. If you already have that id, answer 2xx and stop.
  3. For each reviewCaseId, keep the highest caseVersion, then eventSequence, you’ve seen. Treat an event below that as history, not as the current state.
  4. Answer with a 2xx status within 10 seconds, then do the slower work.
  5. When you need details, read caseUrl with an application key rather than relying on the event body.

Ignore fields you don’t recognize. When the payload shape changes, schemaVersion changes with it; event type names stay the same.

Catch up after an outage

If your endpoint was down or turned off, list the review events VeriProof sent, or tried to send, to that subscription:

GET /v1/review-events?subscriptionId={subscriptionId}&page=1&pageSize=50

Call it on the Customer Portal API as someone with the Manage Integrations permission. Results are newest first. pageSize defaults to 20 and goes up to 100.

{ "subscriptionId": "a41c7e92-5b3d-4f08-8e6a-1d9c2b7f0e54", "events": [ { "event": { "id": "evt_3a6d9f0c2e5b8147a3d6f9c0e2b5a8d1f4c7e0b3", "type": "review.case.decided", "schemaVersion": 1, "…": "the same fields as the delivered event" }, "deliveryStatus": "dead_lettered", "deliveredAt": null } ], "totalCount": 1, "page": 1, "pageSize": 50, "hasMore": false }

deliveryStatus is pending, delivering, retry_scheduled, delivered, or dead_lettered (failed). Run each event through the same handler you use for deliveries; your de-duplication skips the ones you already have.

The list covers events that were sent, or retried and failed, while your endpoint was down. Events from a time the subscription was turned off were never sent to it, so they aren’t listed. Use the missedFrom and missedUntil window from subscription.events_missed to check review work from that period in VeriProof.

This is a recovery read. Don’t poll it to find new work; the webhook is how VeriProof tells you about new events.

Session and platform events

An endpoint can also receive session, application, health, and compliance events, such as session.completed, application.promoted, health.status_changed, and compliance.rule_violation. Those keep their own format: id, type, timestamp, apiVersion, customerId, application, and data. They’re signed and delivered the same way as review events.

Last updated on