---
title: "Initiate Presigned Upload"
method: POST
path: "/upload/initiate"
tags: ["upload"]
---

# Initiate Presigned Upload

`POST /upload/initiate`

## Request

- Base URL: `https://api.seal.net` (the document declares no server; this is the origin it was published from)
- URL: `https://api.seal.net/upload/initiate`
- Auth: none declared

Step 1: Initiate presigned upload for 100K+ concurrent support.

Returns a presigned PUT URL for direct client→storage upload.
Marks file status as "pending" in database.

Uses dedicated signing executor (4 workers) for CPU-bound operations.
Non-blocking for event loop — supports 40K signs/sec per pod.

Flow:
    1. Client calls POST /upload/initiate
    2. Server validates file record exists
    3. Server marks status="pending"
    4. Server returns presigned URL
    5. Client uploads directly to R2 (server NOT in data path)
    6. Client calls POST /upload/confirm

Security:
    - SEAL: Requires X-Owner-Token header
    - AEON/Vault: Requires JWT Bearer token + org membership

## Request body

- UploadInitiateRequest: Initiate presigned upload request: the row registration made, at the length it registered (C1 Р24); its `sha256_hex` is the registration's.
  - `seal_id` string, required: Seal ID (8-char base64url)
  - `file_id` string, uuid, required: The file row from registration
  - `content_type` string: MIME type
  - `content_length` integer, required: Ciphertext length: the registered size

## Response `200`

Successful Response

- UploadInitiateResponse: Presigned upload initiation response: one PUT with Content-MD5.
  - `upload_url` string, required
  - `key` string, required
  - `expires_in` integer, required
  - `use_presigned` boolean
  - `already_verified` boolean

## Other responses

- `422`: Validation Error

---

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