SteveSteve

Create a workflow upload session

POST/api/v1/workflows/{slug}/sessions

Authorization

AuthorizationRequiredBearer <token>

Steve API key, usually scoped to a company. Legacy keys and keys created by platform administrators may be unscoped; company-scoped endpoints reject unscoped keys with 403 Forbidden. Format: Authorization: Bearer aok_...

In: header

Request Body

application/jsonRequired
fileCountRequiredinteger

Number of files to upload. Must fall within the resolved workflow version's upload window, i.e. between uploadStage.minFiles and uploadStage.maxFiles (inclusive). A value outside that window — or a non-integer — is rejected with a 422 validation-error on field fileCount.

Minimum: 1
contentTypesRequiredarray<string>

MIME types for each file to upload, in upload order. The array length MUST equal fileCount, and every entry MUST be one of the workflow version's uploadStage.acceptedFormats. A length mismatch returns a 422 validation-error on field contentTypes; an unaccepted entry returns a 422 validation-error on field contentTypes[i].

clientSubmissionIdRequiredstring
webhookUrlstring

Optional webhook URL notified on session completion. Must be a valid HTTPS URL pointing at a public host. Non-HTTPS URLs, malformed URLs, or hosts that are loopback (localhost, 127.0.0.1), RFC 1918 private ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16), or .internal / .local suffixes are rejected with a 422.

Format: "uri"
metadataobject

Optional arbitrary metadata stored with the session. Constraints, enforced at creation: the serialized JSON must be at most 4096 bytes; nesting is limited to 2 levels; and leaf values must be string, number, or boolean only (no functions, dates, or other types). Violating any of these returns a 422 validation-error on field metadata.

externalUserobject

Optional end-user attribution. When provided, the submission is labeled in the Steve admin UI with (in order of preference) name, email, or id. If omitted, the submission is attributed to the API key that created it.

batchRefstring

Optional client-chosen grouping key, unique per company. Steve creates the batch on first use and increments its total once per newly created session. When processed equals total, completion waits until the newest session in the batch is at least five minutes old; a newer session resets that grace check. This reduces completion while an upload burst is still in flight. A pause longer than five minutes can still complete a batch early; sessions later added with the same reference increase totals but do not emit a second batch.completed event.

Minimum length: 1Maximum length: 128Pattern: "^[A-Za-z0-9._-]+$"

Path Parameters

slugRequiredstring

Workflow slug.

Header Parameters

X-Request-Idstring

Optional caller-supplied request identifier. Maximum length is 128 characters.

Maximum length: 128
curl -X POST "https://your-deployment.convex.site/api/v1/workflows/<string>/sessions" \
  -H "X-Request-Id: <string>" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "fileCount": 1,
    "contentTypes": [
      "string"
    ],
    "clientSubmissionId": "string",
    "webhookUrl": "http://example.com",
    "metadata": {},
    "externalUser": {
      "id": "string",
      "name": "string",
      "email": "string"
    },
    "batchRef": "string"
  }'

Existing pending session returned for the same clientSubmissionId. The Location header also points at the job resource (/api/v1/jobs/{sessionId}).

{
  "sessionId": "string",
  "submissionId": "string",
  "state": "pending",
  "submissionStatus": "created",
  "workflow": {
    "slug": "string",
    "version": 0
  },
  "uploadUrls": [
    {
      "fileIndex": 0,
      "uploadUrl": "http://example.com",
      "r2Url": "http://example.com",
      "contentType": "string",
      "label": "string"
    }
  ],
  "expiresAt": "2019-08-24T14:15:22Z",
  "uploadUrlsExpireAt": "2019-08-24T14:15:22Z"
}