Submission Review
Operate Steve as a headless review queue through the external API.
The submission endpoints let an integrator run manual review outside the Steve UI.
Use them to:
- list submissions for the authenticated company
- fetch full detail, including file download URLs and event history
- inspect and resolve fraud matches
- approve, reject, or cancel submissions
Public status model
Steve exposes the following submission statuses through the external API:
| Status | Meaning |
|---|---|
created | Submission record exists but processing has not started |
processing | Steve is running extraction and fraud checks |
capture_quality_blocked | Processing stopped because the uploaded capture did not meet quality rules |
review | Human review is required |
approved | Approved and waiting for or entering downstream sync |
synced | Approved, and the data was actually delivered downstream (derived) |
rejected | Rejected by a reviewer or integration |
cancelled | Cancelled before approval or sync |
failed | Processing failed for a non-review reason |
For workflow sessions, GET /api/v1/jobs/{sessionId} tells you when processing is done. GET /api/v1/submissions/{submissionId} is the canonical read model for manual review.
List submissions
Supported query parameters:
| Parameter | Meaning |
|---|---|
workflow | Filter to one workflow slug |
status | Filter by public submission status |
fraudStatus | Filter by clean, flagged, or blocked |
cursor | Continue from a previous page |
limit | Page size, clamped to 1..100 |
Example response:
Notes:
- timestamps are ISO 8601 strings
clientSubmissionIdis the caller-supplied idempotency key from session creationextractedDatamay be partial or complete depending on processing state
Get submission detail
Example response:
Important details:
- file download URLs are pre-signed and valid for one hour
eventsare newest-first and capped at 100 entries; allverification_*events are excluded. Public outcome events such asrejectedremain visible, with internalrunIdandpreviousRunIdfields omitted from their details.rejectReasonandcancelReasonare exposed on rejected or cancelled submissions
Fraud match workflow
If a submission is flagged or blocked, inspect the linked fraud matches:
Response shape:
Resolve one match:
Allowed resolutions:
false_positiveconfirmed_fraud
Approvals are blocked while unresolved fraud matches remain.
Reading checkType
checkType is either visual (perceptual-hash image duplicate) or data
(duplicate extracted content). Data duplicates are produced two ways, and both
report checkType: "data":
- an exact match on the workflow's configured identity fields, which always
arrives as
score: 100,similarity: 1.0,status: "block" - a similarity match scored against the workflow's thresholds, which can be
flagorblock
Treat similarity: 1.0 with status: "block" as a certain duplicate rather
than a high score.
Approve, reject, and cancel
Approve
Approves a submission that is currently in review.
Approval returns 409 while product matching is not finished for a workflow that matches products: a line still waits for a reviewer, matching is still running, or it failed. When the organization's product catalog is switched off, approval does not refuse for this reason; it skips the unfinished matching and approves.
Approval returns 409 when verification checks did not pass; a reviewer must approve with a reason. This includes failed, inconclusive, unavailable, stale, or unrun checks on an enabled verification stage. Checks skipped because fraud blocked processing still need to run after the fraud match is resolved. A reviewer can use Run checks in Steve and approve after a current pass, or approve with an audited reason. The external approve endpoint does not accept an override reason; send these cases to a Steve reviewer.
Response:
approved is the terminal status: a submission that reaches it is finished, and for an account with no downstream delivery configured that is the last word you will see.
Where delivery IS configured, approval triggers Steve's downstream sync path and later reads may show synced. It is owned by the delivery ledger, not by review actions, and it requires an actual delivery to have gone out — every target the submission owed, delivered. Anything short of that stays approved: a workflow that declares no delivery targets, a delivery still outstanding, or one skipped for a fixable reason (no customer email on file, or the integration not configured yet) — the last of which stays approved until someone fixes the cause and the delivery is retried.
Reject
Reject requires a human-readable reason.
Cancel
Cancel is available until the submission reaches approved or synced. The reason is optional.
Operational guidance
- Use
GET /api/v1/jobs/{sessionId}to know when a submission is ready for review. - Use
GET /api/v1/submissions/{submissionId}as the canonical source of truth after any action. - If you need file bytes, fetch them immediately after retrieving submission detail because download URLs expire.
- POST review actions share the
writerate-limit bucket. See Error Handling. - Webhooks are useful for notification, but the safest way to render a review UI is still to refetch the submission after each event.
Process a blocked capture anyway
GET /api/v1/submissions/{submissionId} includes files[].captureQuality: null when unmeasured,
otherwise verdict (ok, warn, or blocked), reasons, processedAnyway, and checkedAt.
Each reason includes code, metric, the rounded measured value, threshold, and blocking.
A processed-anyway file keeps the measured verdict; processedAnyway: true records the bypass.
Send no body. This authorizes one run with the same files and workflow version. It returns 202
with the existing submission action response and current submissionStatus. Repeating the request
while processing, or after that override finished without another capture-quality block, returns
202 without starting another run. A completed override blocked again can start another run.
The endpoint requires current workflow access. It returns 403 if the module is off, the workflow
is inactive, or its company grant was revoked; 404 for a missing or other-company submission;
409 if there is no eligible block or recorded measurement, or delivery history exists.
A failed API job returns to submitted and its old result is cleared. Poll the same session ID
or receive a new webhook with a generation suffix in its event ID. This authorization does not
cast calibration votes, approve the result, or bypass other processing checks.
Only this endpoint reopens the job. When someone clicks Process anyway in the Steve admin panel,
the submission is processed again, but the API job stays failed and no new session webhook is
sent. Read the outcome with GET /api/v1/submissions/{submissionId}. If your integration needs the
webhook, trigger the rerun through this endpoint instead of the panel.
Replace a photo with a new capture
Files cannot be added to a submission after its session was submitted, so a retake is a new session and a new submission. Duplicate checks compare the new submission with earlier ones, by image and by the extracted identity fields (for example receipt number and date). Cancelled, rejected, and failed submissions are not compared.
To replace a capture without the retake being flagged as a duplicate of the original:
- Cancel the original with
POST /api/v1/submissions/{submissionId}/cancel, for example with the reason"Replaced by a new photo". - Create a new session with the new photo.
A submission that is already approved or synced cannot be cancelled. A retake of it is
correctly flagged. A duplicate match never rejects a submission on its own: the submission goes to
review with fraudStatus set. If the match is a false positive, resolve it as false_positive
and approve the submission.
A multi-page PDF remains one submission. Each extracted field can carry an absolute page citation; item fields can carry one page per item. OCR-text and page-image reads are compared independently. Disagreement, missing citations, unavailable or truncated reads and failed pages require human review, even at full model confidence or after passing verification. Machine evidence remains immutable when a reviewer edits a field. The original PDF and page images/markdown expire under the workflow's media retention policy; extracted values and evidence remain. Both Classic and Deck show a page viewer for multi-page files, including when extraction failed before evidence was saved.
In Deck, the viewer opens on the page of the next field to check and turns to the next field's page as you settle each one, until you turn a page yourself. Under the page, a strip shows every page; a page with fields still to check carries their count, and a page that could not be turned into an image says so. Use the arrows, the arrow keys or the strip to move, zoom and rotate to read small print, and full screen to page through the whole document. Under the page, the viewer lists the fields read from it; choose one to go to its row. The PDF button opens the original document. In a duplicate comparison, a multi-page PDF is shown by its first page.
In Classic, use Previous, Next or the page list to move through the document. A failed page is marked in the list. Download original PDF opens the original document.
Choose a field's page number to open its source page; line items have a citation for each item. A missing or zero page number is not a citation. In Deck, each clean value shows its pages beside it, and a page number is highlighted while that page is on screen. Flagged fields appear in Classic's Failed group and Deck's To check rows, including fields the workflow does not allow you to edit. Each shows a plain-English reason and every value the reads found, with its pages; a value both reads gave is shown once. If OCR itself found conflicting values, each one is shown with its own page.
A sentence above the fields explains any incomplete reads or failed pages. In Deck, the value stored now is marked; Use this value on another one saves it in one click, and Confirm keeps the stored value. You can still type a different value. A non-editable flagged field shows the values without Use this value; Confirm records that you checked it. These actions record the review without replacing the original machine evidence.
In Deck, a line-items field to check shows its lines as a table under the row, so you see what Confirm keeps. Edit line items replaces the table with the editor, and Cancel brings the table back. The lines stay shown after you confirm or save them, and a line-items field you cannot edit shows them the same way. In the editor, text cells wrap and grow with long text: Enter saves the lines, and Shift+Enter starts a new line in a cell.
When the workflow version a submission was checked against has reference images, Deck shows them under the evidence, each with its label. They are kept apart from the submission's photos: they are not counted with them, and they open in their own viewer, where you can zoom in to compare. They come from that version, not from later edits to the workflow. A reference image that cannot be loaded says so.
When the workflow chooses references by product key, Deck shows only the references that were sent with this submission, not the whole library. A sentence above them names the product key, and each label says whether it matched by exact key, key prefix or as a shared reference. When no reference matched and the AI analysis was skipped, Deck shows the reason under the summary and above the references, for example that no product key was sent, and no references. The summary asks you to fill in the fields from the photos, and each field reads as not analysed rather than as read or missing from the photo. When only shared references were used, the same line under the summary says so. See Reference images.