---
title: "Create a client token for an authorized private batch upload"
method: POST
path: "/uploads"
tags: ["Batches and files"]
---

# Create a client token for an authorized private batch upload

`POST /uploads`

## Request

- Base URL: `https://www.sanctionskit.com/api/v1`
- URL: `https://www.sanctionskit.com/api/v1/uploads`
- Auth: HTTP bearer
- TypeScript: <https://skmtc.dev/sanctionskit/apis/sanctionskit-api/docs/uploads/post.ts> (a function with typed inputs; its response is checked against the schema)

Required API key scope: batches:write.

Call through @vercel/blob/client with the pathname from POST /uploads/intent, access private and multipart false. Upload NDJSON with one ScreeningRequest per line, up to 10000 rows. The provider-only upload-completed callback is excluded from this consumer reference.

## Request body

- UploadTokenRequest
  - `type` 'blob.generate-client-token', required: Fixed client-token request discriminator.
  - `payload` object, required: Provider client-token payload. Use the exact pathname from the authorized upload intent.
    - `pathname` string, required: Exact pathname from POST /uploads/intent; it is bound to your organization and key environment.
    - `clientPayload` string, nullable, required: Client metadata field used by the upload protocol. Send null when no metadata is needed.
    - `multipart` unknown, required

## Response `200`

Successful response. The response is the documented raw JSON or file content, without a data envelope. Check Content-Type before decoding.

- UploadTokenResponse
  - `type` 'blob.generate-client-token', required
  - `clientToken` string, required: Short-lived private upload token. Treat it as a secret and pass it only to the authorized upload client; do not log it.

## Other responses

- `400`: **invalid_request** — Correct the request fields, resource identifiers, JSON body or query parameters before retrying. **upload_intent_required** — Request an upload intent and pass its exact pathname. **invalid_upload** — Use the documented single-upload protocol; multipart must be false.
- `401`: **authentication_required** — Send Authorization: Bearer with a valid API key. An omitted header can produce authentication_required; invalid supplied credentials produce invalid_api_key. **invalid_api_key** — Use an active key for the intended environment.
- `403`: **permission_denied** — Ask an organization owner to grant the required role or API-key scope. **insufficient_scope** — Use a key with the scope stated in this operation.
- `405`: **method_not_allowed** — Use a method in the Allow response header. OPTIONS lists supported methods; HEAD follows GET authorization and returns no body.
- `408`: **invalid_request** — Reconnect and retry using the same idempotency key and identical input where supported.
- `409`: **upload_token_expired** — Create a fresh upload intent.
- `413`: **response_too_large** — Reduce the requested page size or use the documented segmented case archive. No evidence is silently truncated.
- `415`: **invalid_request** — Use Content-Type: application/json and an uncompressed UTF-8 body.
- `429`: **rate_limited** — Wait for the request window to reset and retry with backoff.
- `500`: **internal_error** — Retry with backoff. For writes reuse the same idempotency key and identical input; include requestId when contacting support.
- `503`: **temporarily_unavailable** — Honor Retry-After when present and retry with bounded backoff. Follow this endpoint’s retry contract; preserve the same key and input for idempotent writes. Contact support with requestId if the failure persists.

---

[API](https://skmtc.dev/sanctionskit/apis/sanctionskit-api.md) - [All operations](https://skmtc.dev/sanctionskit/apis/sanctionskit-api/llms.txt) - [OpenAPI document](https://skmtc.dev/sanctionskit/apis/sanctionskit-api/revisions/ee35d211051a?raw)
