---
title: "Create a world or allocate its next version and return a presigned multipart POST policy (6 MiB ZIP; 10 packages/account/day)."
method: POST
path: "/api/v1/uploads"
---

# Create a world or allocate its next version and return a presigned multipart POST policy (6 MiB ZIP; 10 packages/account/day).

`POST /api/v1/uploads`

## Request

- Base URL: `https://portamora.app`
- URL: `https://portamora.app/api/v1/uploads`
- Auth: one of:
  - API key in cookie `__Host-session`
  - HTTP bearer

Create a world or allocate its next version and return a presigned multipart POST policy (6 MiB ZIP; 10 packages/account/day). Requires worlds:write. Repeat the same Idempotency-Key for retries; keys are retained for 24 hours.

## Headers

- `Idempotency-Key` string, required
- `x-amz-content-sha256` string, required

## Request body

- object
  - `worldId` string: Case-sensitive world identifier with 10 safe-alphabet characters after the prefix.
  - `notes` string
  - `contentType` 'application/zip'

## Response `201`

Successful private response; Cache-Control: no-store.

- object
  - `id` string, required: Case-sensitive upload identifier with 10 safe-alphabet characters after the prefix.
  - `worldId` string, nullable, required: Case-sensitive world identifier with 10 safe-alphabet characters after the prefix.
  - `versionId` string, nullable, required: Case-sensitive version identifier with 10 safe-alphabet characters after the prefix.
  - `kind` 'package' | 'avatar' | 'thumbnail', required
  - `contentType` 'application/zip' | 'image/png' | 'image/jpeg' | 'image/webp', required
  - `status` 'pending' | 'queued' | 'processing' | 'ready' | 'rejected' | 'failed', required
  - `outputs` object, required
    - `thumbnailKey` string
    - `thumbnailLargeKey` string
    - `avatarKey` string
    - `avatarSmallKey` string
  - `error` string, nullable, required
  - `createdAt` string, date-time, required
  - `expiresAt` string, date-time, required
  - `maxBytes` integer, required
  - `parts` object[]
    - `partIndex` integer, required
    - `bytes` integer, required
    - `sha256` string, required
  - `files` object[]
    - `path` string, required
    - `bytes` integer, required
    - `sha256` string, required
  - `versionNumber` integer, required
  - `upload` object: Present while the upload is pending. Replayed requests may already be processing or complete.
    - `id` string, required: Case-sensitive upload identifier with 10 safe-alphabet characters after the prefix.
    - `expiresAt` string, date-time, required
    - `url` string, required: An absolute HTTPS storage URL, or a relative /api/v1/local-uploads/... path on the local site.
    - `fields` object, required

## Other responses

- `400`: Invalid input or expired sign-in link.
- `401`: Authentication required.
- `403`: Missing scope, browser session, fresh sign-in, or matching Origin.
- `404`: Missing resource or resource owned by someone else.
- `409`: Conflicting handle, idempotency key, or version state.
- `410`: The upload window has expired. Allocate a new upload with a new key.
- `413`: Request body or uploaded file exceeds its limit.
- `429`: Rate limit reached. Retry-After header and details.retryAt give the next allowed attempt.
- `503`: Temporarily unavailable.

---

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