---
title: "Prepare a direct file upload"
method: POST
path: "/api/projects/{id}/files/uploads"
---

# Prepare a direct file upload

`POST /api/projects/{id}/files/uploads`

## Request

- Base URL: `https://editor.pascal.app`
- URL: `https://editor.pascal.app/api/projects/{id}/files/uploads`
- Auth: HTTP bearer

Requires project membership and OAuth scene:write when using OAuth. Returns a short-lived signedUrl; PUT raw bytes there with the supplied Content-Type, then complete at this endpoint with PUT. The file is listed only after completion. Maximum 500 MiB; SVG is refused. Names contain no path separators or control characters.

## Request body

- object
  - `name` string, required
  - `mimeType` string, required
  - `size` integer, required
  - `type` 'scan' | 'guide' | 'image' | 'document' | 'other'
  - `source` 'editor' | 'ai_chat' | 'api' | 'import'

## Response `201`

Upload destination; retain id and storageKey for completion retries

- object
  - `id` string, required
  - `storageKey` string, required
  - `signedUrl` string, uri, required

## Other responses

- `400`: Invalid file request
- `401`: Authentication required
- `403`: Missing scene:read or scene:write OAuth scope
- `404`: Project or file not accessible to this workspace member
- `415`: Unsupported file type

---

[API](https://skmtc.dev/pascal/apis/pascal-editor-scene-api.md) · [All operations](https://skmtc.dev/pascal/apis/pascal-editor-scene-api/llms.txt) · [OpenAPI document](https://skmtc.dev/pascal/apis/pascal-editor-scene-api/revisions/08f1f3f41067?raw)
