---
title: "Mint the slot behind an upload link (called by the upload page)"
method: POST
path: "/v1/upload-links/{token}/uploads"
tags: ["uploads"]
---

# Mint the slot behind an upload link (called by the upload page)

`POST /v1/upload-links/{token}/uploads`

## Request

- Base URL: `https://api.framelane.io`
- URL: `https://api.framelane.io/v1/upload-links/{token}/uploads`
- Auth: none declared

Authenticated by the link token alone — this is what the upload page calls once the person has picked a file. Returns the same shape as `POST /v1/uploads`; the page then PUTs the bytes to `first_party_upload_url` (or `upload_url`). Calling it again re-points the link at a fresh slot, so a retried upload just works.

## Path parameters

- `token` string, required

## Request body

- LinkUploadRequest
  - `content_type` string, required: MIME type of the file the person picked.
  - `filename` string, nullable: The file's name, for display.
  - `duration` number, nullable: Browser-probed duration in seconds (video/audio).
  - `width` integer, nullable: Browser-probed pixel width.
  - `height` integer, nullable: Browser-probed pixel height.

## Response `201`

Successful Response

- UploadOut: Response from POST /v1/uploads.
  - `upload_url` string, nullable: GCS resumable upload URL. PUT your file bytes here with the correct Content-Type. **null** when you sent `content_base64`: the bytes are already stored, so there is no slot left to fill.
  - `source_url` string, required: CDN URL for the uploaded file. Pass this as source_url in render/task requests.
  - `expires_at` string, date-time, required: When the upload_url expires (1 hour from now).
  - `uploaded` boolean: True when this call also stored the file (you sent `content_base64`), so `source_url` is usable immediately. False means only a slot was minted and the bytes are still yours to PUT.
  - `asset_id` string, nullable: The media asset registered for this upload — poll it with `GET /v1/workspace/assets/{id}`. Null for fonts, which are storable but are not timeline media and so get no asset row.
  - `first_party_upload_url` string, nullable: The same upload session as `upload_url`, on a Framelane hostname. Use it when your network allows `*.framelane.io` but not `storage.googleapis.com` — same protocol, same chunks, same expiry. Null when you sent `content_base64`, or when this deployment has no first-party upload host.

## Other responses

- `404`: Unknown or expired link.
- `422`: Unsupported content_type.

---

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