---
title: request_upload_url
description: Get a short-lived upload URL for a website. PUT files directly with filename and content type. Supports asset replacement via asset_id.
section: MCP Reference
order: 7
---

# request_upload_url

Get a short-lived upload URL for a website. The returned URL is a session-based
endpoint — PUT file bytes directly to it with the filename as a query parameter.

Prefer `upload_asset` with the `url` parameter for typical image uploads and
migrations. `request_upload_url` is intended for large local files that exceed
`upload_asset`'s size limits.

## Usage

1. Call `request_upload_url` with the website identifier
2. PUT files to the returned URL with the filename as a query parameter and the matching `Content-Type` header:
   ```
   PUT https://pageweave.dev/api/v1/websites/uploads/:id?filename=photo.jpg
   Content-Type: image/jpeg
   [file bytes]
   ```
3. Session expires in 10 minutes

## Parameters

- `website` — Website subdomain, domain, or UUID
- `asset_id` — Optional existing asset UUID. When set, the PUT replaces that asset's bytes (URL/filename preserved) instead of creating a new asset. The `Content-Type` header on the PUT must match the existing asset's content type. If the asset is deleted between the `request_upload_url` call and the PUT, the PUT returns 422 with `"Asset not found"`.

## Response

| Field | Type | Description |
|-------|------|-------------|
| `upload_url` | string | Session-based URL for the PUT upload |
| `expires_at` | string (ISO 8601) | When the session expires |
| `storage` | object | `used_bytes` and `limit_bytes` for the website |

## Size Limits

Effective max = min(per-type cap, remaining website storage):

| Content type | Cap |
|---|---|
| Images | 5MB |
| Fonts | 2.5MB |
| Video | 15MB |
| Audio | 15MB |
| Other (PDF, docs, archives) | 10MB |

## OAuth Scopes

| Action | Scope |
|--------|-------|
| request_upload_url | `asset:write` |
| request_upload_url with asset_id (replace) | `asset:write` |
