SteveSteve

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:

StatusMeaning
createdSubmission record exists but processing has not started
processingSteve is running extraction and fraud checks
capture_quality_blockedProcessing stopped because the uploaded capture did not meet quality rules
reviewHuman review is required
approvedApproved and waiting for or entering downstream sync
syncedApproved and synced downstream
rejectedRejected by a reviewer or integration
cancelledCancelled before approval or sync
failedProcessing 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

curl "$BASE_URL/api/v1/submissions?status=review&workflow=receipt-ocr&limit=20" \
  -H "Authorization: Bearer $STEVE_API_KEY"

Supported query parameters:

ParameterMeaning
workflowFilter to one workflow slug
statusFilter by public submission status
fraudStatusFilter by clean, flagged, or blocked
cursorContinue from a previous page
limitPage size, clamped to 1..100

Example response:

{
  "data": [
    {
      "id": "jx7sub456submissions",
      "submissionStatus": "review",
      "fraudStatus": "flagged",
      "fraudScore": 72.5,
      "workflow": {
        "slug": "receipt-ocr",
        "name": "Receipt OCR",
        "version": 3
      },
      "extractedData": {
        "merchantName": "Biedronka",
        "totalAmount": 123.45
      },
      "confidence": 0.96,
      "createdAt": "2026-03-25T10:00:00.000Z",
      "clientSubmissionId": "order-1711353600000"
    }
  ],
  "pagination": {
    "hasMore": false,
    "nextCursor": null
  }
}

Notes:

  • timestamps are ISO 8601 strings
  • clientSubmissionId is the caller-supplied idempotency key from session creation
  • extractedData may be partial or complete depending on processing state

Get submission detail

curl "$BASE_URL/api/v1/submissions/jx7sub456submissions" \
  -H "Authorization: Bearer $STEVE_API_KEY"

Example response:

{
  "id": "jx7sub456submissions",
  "submissionStatus": "review",
  "fraudStatus": "flagged",
  "fraudScore": 72.5,
  "extractedData": {
    "merchantName": "Biedronka",
    "totalAmount": 123.45,
    "currency": "PLN"
  },
  "confidence": 0.96,
  "fieldConfidences": {
    "merchantName": 0.99,
    "totalAmount": 0.95
  },
  "certainty": 0.94,
  "aiSummary": "Receipt from Biedronka with one flagged fraud match.",
  "failedReason": null,
  "rejectReason": null,
  "cancelReason": null,
  "workflow": {
    "id": "jx7wf001workflows",
    "slug": "receipt-ocr",
    "name": "Receipt OCR",
    "version": 3
  },
  "files": [
    {
      "id": "jx7file001submissionFiles",
      "fileIndex": 0,
      "label": "receipt",
      "mimeType": "image/jpeg",
      "fileSize": 245120,
      "downloadUrl": "https://r2.example.com/files/receipt.jpg?X-Amz-Signature=abc123"
    }
  ],
  "fraudMatches": [
    {
      "id": "jx7fm001submissionFraudMatches",
      "checkType": "visual",
      "score": 72.5,
      "similarity": 0.88,
      "status": "flag",
      "resolution": null,
      "resolvedBy": null,
      "resolvedAt": null
    }
  ],
  "events": [
    {
      "type": "ready_for_review",
      "occurredAt": "2026-03-25T10:01:40.000Z",
      "details": {
        "compliance": 0.96,
        "fraudStatus": "flagged"
      }
    }
  ],
  "clientSubmissionId": "order-1711353600000",
  "metadata": {
    "orderId": "12345"
  },
  "createdAt": "2026-03-25T10:00:00.000Z"
}

Important details:

  • file download URLs are pre-signed and valid for one hour
  • events are newest-first and capped at 100 entries
  • rejectReason and cancelReason are exposed on rejected or cancelled submissions

Fraud match workflow

If a submission is flagged or blocked, inspect the linked fraud matches:

curl "$BASE_URL/api/v1/submissions/jx7sub456submissions/fraud-matches" \
  -H "Authorization: Bearer $STEVE_API_KEY"

Response shape:

{
  "data": [
    {
      "id": "jx7fm001submissionFraudMatches",
      "checkType": "visual",
      "score": 72.5,
      "similarity": 0.88,
      "status": "flag",
      "resolution": null,
      "resolvedAt": null,
      "targetSubmission": {
        "id": "jx7sub200submissions",
        "createdAt": "2026-03-25T09:43:20.000Z"
      }
    }
  ],
  "pagination": {
    "hasMore": false,
    "nextCursor": null
  }
}

Resolve one match:

curl "$BASE_URL/api/v1/submissions/jx7sub456submissions/fraud-matches/jx7fm001submissionFraudMatches/resolve" \
  -X POST \
  -H "Authorization: Bearer $STEVE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"resolution":"false_positive"}'

Allowed resolutions:

  • false_positive
  • confirmed_fraud

Approvals are blocked while unresolved fraud matches remain.

Approve, reject, and cancel

Approve

Approves a submission that is currently in review.

curl "$BASE_URL/api/v1/submissions/jx7sub456submissions/approve" \
  -X POST \
  -H "Authorization: Bearer $STEVE_API_KEY"

Response:

{
  "submissionId": "jx7sub456submissions",
  "workflow": {
    "slug": "receipt-ocr",
    "version": 3
  },
  "submissionStatus": "approved"
}

Approval triggers Steve's downstream sync path. Later reads may show synced.

Reject

Reject requires a human-readable reason.

curl "$BASE_URL/api/v1/submissions/jx7sub456submissions/reject" \
  -X POST \
  -H "Authorization: Bearer $STEVE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"reason":"Document is illegible and cannot be verified."}'

Cancel

Cancel is available until the submission reaches approved or synced. The reason is optional.

curl "$BASE_URL/api/v1/submissions/jx7sub456submissions/cancel" \
  -X POST \
  -H "Authorization: Bearer $STEVE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"reason":"Duplicate submission from the same customer."}'

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 write rate-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.

On this page