---
title: "Get a one-time PUT URL for a large file"
method: POST
path: "/upload-sessions"
tags: ["Uploads"]
---

# Get a one-time PUT URL for a large file

`POST /upload-sessions`

## Request

- Base URL: `https://putit.online/api/v1`
- URL: `https://putit.online/api/v1/upload-sessions`
- Auth: one of:
  - none
  - HTTP bearer
  - OAuth 2 (authorization code, authorization URL `https://putit.online/oauth/authorize`, token URL `https://putit.online/oauth/token`, scopes: `links:read`, `links:write`, `account:read`)

Reserves a link and returns upload_url. PUT the raw bytes there, then poll get_link.

## Request body

- object
  - `filename` string, required: Name of the file that will be uploaded, including extension.
  - `size_bytes` integer: Expected size, checked against your plan limit up front.
  - `slug` string: Custom link name (3-40 letters, digits, dashes); available on plans with custom names.
  - `password` string: Visitors must enter this password to open the link; available on plans with password protection.

## Response `201`

OK

- object
  - `upload_url` string, required: One-time URL: PUT the raw file bytes here (no auth header needed).
  - `method` 'PUT', required
  - `headers` object, required
  - `max_bytes` number, required
  - `expires_at` string, required
  - `complete_url` string: When present: POST here (no body) after the PUT finishes. The curl command already does it.
  - `curl` string, required: Ready-to-run command for the user.
  - `link` object, required
    - `slug` string, required
    - `url` string, required: The public link to share.
    - `status` 'awaiting_upload' | 'checking' | 'live' | 'in_review' | 'unpublished' | 'publishing' | 'removed' | 'expired' | 'deleted', required: checking = not live yet (poll get_link); live = shareable; unpublished = not published; publishing = will be live soon (poll get_link); in_review = not available right now; removed = removed by moderation (see removed_reason, appeal_url).
    - `status_message` string, required
    - `content_url` string: Only when live, for sites and single files: where the content itself is served (https://<slug>.putitcdn.com/…). Share `url` instead; it always works.
    - `checkout_url` string: Only with status unpublished: the page where the uploader can publish this link.
    - `removed_reason` string: Only with status removed: why, in plain words.
    - `removed_category` string, nullable: Only with status removed: the moderation category (malware, phishing, explicit, …); null when not disclosed.
    - `appeal_url` string: Only with status removed: mailto link to appeal to abuse@putit.online.
    - `kind` string, required: html | site | file | bundle | pending
    - `title` string, required
    - `size_bytes` number, required
    - `file_count` number, required
    - `views` number, nullable, required: View count; null when the link's account plan has no view counts, or the link has no account.
    - `permanent` boolean, required
    - `password_protected` boolean, required
    - `created_at` string, required
    - `expires_at` string, nullable, required: ISO time the link stops working; null for permanent links.
    - `manage_url` string: Private page to manage/delete the link. Only returned on creation; keep it secret.
    - `manage_token` string: Secret token returned on creation for every new link (keep it secret). Anonymous callers pass it to get_link/delete_link; a link in an account is managed by that account instead.

## Other responses

- `400`: Invalid request
- `401`: Authorization required or token invalid
- `402`: Subscription required (see upgrade_url)
- `403`: Blocked: VPN/proxy, banned uploader or missing scope
- `422`: Rejected by the safety check
- `429`: Rate limited (see Retry-After)

---

[API](https://skmtc.dev/putit/apis/put-it-online-api.md) · [All operations](https://skmtc.dev/putit/apis/put-it-online-api/llms.txt) · [OpenAPI document](https://skmtc.dev/putit/apis/put-it-online-api/revisions/a0c9fe8d4301?raw)
