API changelog
Approved breaking changes to Steve API version 1, with migration steps.
Version 1 is additive-only (see Compatibility). This page records the rare exceptions: changes that existing integrations must act on. Selected additive changes are listed below; the API reference always describes the current contract.
Each entry names the pull request that made the change, what changed, why, and what clients must do.
No breaking changes have been made to v1.
2026-11-13: AI provider throttling and outages (behaviour change)
Not a breaking change: no request, response or webhook shape changed. When the AI provider throttles Steve or is briefly unavailable, a job now stays submitted while Steve retries after 5 minutes and then after 15 more, and it can still complete. Before, such a job often failed within a few minutes. A job that does fail because of a provider outage now fails later than before (20 minutes or more instead of a few), and its batch completion and terminal webhook wait with it. Clients with their own polling deadline should allow for this or use webhooks. See Polling and jobs. Existing integrations require no migration.
2026-11-10: request body size limit (behaviour fix)
Request bodies over 1 MiB (1,048,576 bytes) are now refused with 413 and the payload-too-large problem type, before the request is processed. This is a new limit on every operation that reads a JSON body: POST /api/v1/workflows/{slug}/sessions, POST /api/v1/submissions/{submissionId}/reject, /cancel and /fraud-matches/{matchId}/resolve, POST /api/v1/webhooks/test and the shelf session operations. Some string fields have no length limit of their own, so a client that sends very large values must keep the whole body under 1 MiB. A body built within the documented field limits (4 KB metadata, file names, a webhook URL) stays far below it.
2026-11-10: API access switched off for an organization (behaviour fix)
When the API Access module is switched off for an organization, every /api/v1 request made with a key of one of its companies now answers 403 with the forbidden problem type. Before, those keys kept working; only key management was blocked. Turning the module back on restores the keys. Existing integrations of organizations with API access enabled require no migration.
2026-11-10: invalid cursors, malformed ids and the job status slug (behaviour fix)
GET /api/v1/submissions and GET /api/v1/workflows answer 400 validation-error with a field error on cursor when the cursor is not one the API issued. Before, the submissions list restarted at the first page or answered 500, and the workflows list answered an empty page. A workflows cursor stays valid when its workflow is archived or deactivated: the next page continues after it. GET /api/v1/jobs/{sessionId}, GET /api/v1/submissions/{submissionId} and the submission sub-routes answer 404 not-found for a path id that is not an id, instead of 500. GET /api/v1/jobs/{sessionId} with a key that has no company now answers the key-not-company-scoped problem type documented for every company-scoped route, instead of forbidden; the status stays 403. Existing integrations require no migration.
2026-11-10: idempotent session create replays (behaviour fix)
A retry of POST /api/v1/workflows/{slug}/sessions with the same clientSubmissionId while the first session is pending returns that session's original expiresAt and the workflow version it was created on. Before, it reported an expiry 30 minutes after the retry and the workflow's latest version, and a retry after a new version was published could fail validation against that version. The retry's body is still not compared with the first request. Existing integrations require no migration.
2026-11-10: webhook test probe and CORS (behaviour fix)
POST /api/v1/webhooks/test now answers 422 when the URL's host resolves to a private, loopback, link-local or metadata address, and checks the address again when it connects. A failed probe reports "Request failed" or "Request timed out" in error instead of the connection error text. OPTIONS /api/v1/jobs/{sessionId} now answers the same CORS preflight as the other routes, and the Authorization scheme is matched case-insensitively (bearer and BEARER work, as does more than one space before the key). Existing integrations require no migration.
2026-11-04: keyed reference images (additive)
Not a breaking change: no request/response change, no webhook payload change and no OpenAPI change. A workflow can choose its reference images by a product key read from a top-level field of the session metadata (for example "metadata": { "model": "RT641N4AFE1" }) when you create a session with POST /api/v1/workflows/{slug}/sessions. With the workflow's default setting, a submission that sends no key, or a key no reference matches, goes to review with empty data fields and no AI analysis, instead of being analysed. See Reference images. Existing integrations require no migration.
2026-10-28: switching the product catalog off (behaviour fix)
Not a breaking change: no request or response shape changed. Approving a submission (POST /api/v1/submissions/{submissionId}/approve) no longer answers 409 for unfinished product matching when the organization's product catalog is switched off; Steve skips the matching and approves. matchedItems is then [], so submission.approved can list fewer lines than session.review_required. An Open Loyalty target set to send nothing when no line matched now also sends nothing when matching was skipped; retries of an already planned body are unchanged. See Product matching. Existing integrations require no migration.
2026-10-23: multi-page PDF evidence (additive)
Opted-in workflows expose upload.pdfPages.maxPages. Submission files may include pageCount; submission detail may include pages and pageEvidence. Job results and webhook result may include the same compact evidence. A PDF above the workflow limit is still refused as 422 files-invalid, with a per-file message naming its actual count and the limit. Existing integrations require no migration.