Documents

Request a presigned document upload URL

**Step 1 of the two-step presigned document upload.** Validates the declared file (PDF/JPG/PNG, ≤25 MB intent) and returns a short-lived, single-use **signed PUT URL** (`uploadUrl`), the computed `storagePath`, and an opaque `uploadRef`. **The binary bytes never travel through this API call.** After this returns, the caller PUTs the raw file bytes directly to `uploadUrl` (a plain HTTP `PUT` with the file as the request body and the matching `Content-Type`) — out of band — then calls `POST /projects/{id}/documents` with the `uploadRef` to register the document (step 2). This is how binary upload is supported via the API/MCP without bytes passing through the JSON request (ADR 0001 §5). Admin or the project's Site Manager; blocked on read-only/archived projects. `audience` applies to Project Information (`kind: info`) only.

POST
/projects/{id}/documents/upload-url

Step 1 of the two-step presigned document upload. Validates the declared file (PDF/JPG/PNG, ≤25 MB intent) and returns a short-lived, single-use signed PUT URL (uploadUrl), the computed storagePath, and an opaque uploadRef.

The binary bytes never travel through this API call. After this returns, the caller PUTs the raw file bytes directly to uploadUrl (a plain HTTP PUT with the file as the request body and the matching Content-Type) — out of band — then calls POST /projects/{id}/documents with the uploadRef to register the document (step 2). This is how binary upload is supported via the API/MCP without bytes passing through the JSON request (ADR 0001 §5).

Admin or the project's Site Manager; blocked on read-only/archived projects. audience applies to Project Information (kind: info) only.

Authorization

x-api-key<token>

The per-tenant API key, copied from Settings → API & integrations. Sent as the x-api-key request header. The key is tenant-scoped and acts with Admin-equivalent, tenant-wide access.

In: header

Path Parameters

id*string

Resource id.

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

application/json

application/json

application/json

curl -X POST "https://example.com/projects/497f6eca-6276-4993-bfeb-53cbbbba6f08/documents/upload-url" \  -H "Content-Type: application/json" \  -d '{    "kind": "ohs",    "title": "string",    "filename": "string",    "contentType": "string"  }'
{  "uploadRef": "string",  "storagePath": "string",  "uploadUrl": "string",  "bucket": "string",  "kind": "ohs"}
{  "error": {    "code": "unauthorized",    "message": "Missing or invalid API key."  }}
{  "error": {    "code": "read_only",    "message": "Your subscription is inactive. This action is read-only."  }}
{  "error": {    "code": "not_found",    "message": "Not found."  }}
{  "error": {    "code": "validation",    "message": "One or more inputs are invalid.",    "fields": {      "fieldName": "A message explaining what's wrong with this field."    }  }}