API Reference
The sharedrop REST API lets you upload, manage, and share HTML pages programmatically.
Base URL
https://sharedrop.cloud/api/v1
Authentication
All requests require a Bearer token in the Authorization header:
curl -H "Authorization: Bearer sd_your_api_key_here" \
https://sharedrop.cloud/api/v1/pages
See Authentication for details on obtaining and managing API keys.
Rate Limits
All API requests are rate-limited per API key based on your plan tier. Rate limit information is included in response headers.
Response Headers
| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests allowed in the current window |
X-RateLimit-Remaining | Requests remaining in the current window |
X-RateLimit-Reset | Unix timestamp when the window resets |
Limits by Tier
| Endpoint | Free | Pro | Team |
|---|---|---|---|
| Upload | 20/min | 100/min | 200/min |
| List / Read / Update | 60/min | 300/min | 600/min |
| Delete / Share | 30/min | 150/min | 300/min |
Response Format
Success
{
"data": { ... }
}
List (Paginated)
{
"data": [ ... ],
"pagination": {
"next_cursor": "uuid-or-null",
"has_more": true
}
}
Error
{
"error": {
"code": "ERROR_CODE",
"message": "Human-readable description"
}
}
Error Codes
| Code | HTTP Status | Description |
|---|---|---|
UNAUTHORIZED | 401 | Invalid or missing API key |
RATE_LIMIT_EXCEEDED | 429 | Too many requests. Check X-RateLimit-* headers. |
PAGE_NOT_FOUND | 404 | Page does not exist or you don't have access |
VALIDATION_ERROR | 400 | Invalid request body or parameters |
PAGE_LIMIT_REACHED | 403 | Page count limit exceeded for your plan |
FILE_SIZE_EXCEEDED | 413 | File exceeds the size limit for your plan |
Endpoints
Upload a Page (streamed)
The legacy inline create endpoint has been retired and now returns
410 Gone. Upload via the streamed flow below, the CLI, or MCP.
Uploading is a streamed, three-step flow. The file bytes are PUT directly to object storage out-of-band, so there is no request-body size cap on the function.
Supported file types: HTML (.html, .htm), MHTML web archives (.mhtml, .mht), Markdown (.md, .markdown), PDF (.pdf), JSON (.json), JSONL (.jsonl), source code and plain text (.js, .ts, .py, .css, .sql, .sh, .txt, and similar), Word documents (.docx), spreadsheets (.csv, .xlsx), and images (.png, .jpg, .jpeg, .webp, .gif, .avif, .bmp, .ico, .apng, .svg, .heic, .heif, .tif, .tiff). Documents (everything except images and video) upload on every tier; images and video require Pro.
Step 1 — sign
POST /api/upload/sign
Reserve an object key, run the tier and storage gate, and mint a short-lived upload token.
Request Body (JSON):
| Field | Type | Required | Description |
|---|---|---|---|
filename | string | Yes | Filename including extension (e.g. report.pdf) |
content_type | string | Yes | MIME type (e.g. application/pdf) |
size_bytes | number | Yes | Exact body size in bytes — must match the Content-Length of the PUT |
workspace_id | string | No | Upload to a specific workspace |
curl -X POST \
-H "Authorization: Bearer sd_..." \
-H "Content-Type: application/json" \
-d '{"filename": "report.pdf", "content_type": "application/pdf", "size_bytes": 482190}' \
https://sharedrop.cloud/api/upload/sign
The response includes an upload_url, a 5-minute upload_token, a finalize_url, and the object_key.
Step 2 — PUT the bytes
Stream the file bytes directly to the upload_url returned by step 1, authenticating with the upload_token:
curl -X PUT "$UPLOAD_URL" \
-H "Authorization: Bearer $UPLOAD_TOKEN" \
-H "Content-Type: application/pdf" \
-H "Content-Length: $(stat -f%z report.pdf)" \
--data-binary @report.pdf
Step 3 — finalize
POST /api/upload/finalize
Validate the token, sanitise the uploaded bytes, publish the page, and create the page row.
Request Body (JSON):
| Field | Type | Required | Description |
|---|---|---|---|
object_key | string | Yes | The object_key returned by step 1 |
upload_token | string | Yes | The upload_token returned by step 1 |
title | string | No | Page title. Defaults to the document title (HTML/PDF) or filename stem |
visibility | string | No | private (default), shared, or public |
mode | string | No | HTML only: static or interactive (default: your account's default upload mode, initially interactive; configure in Settings). Ignored for non-HTML kinds |
workspace_id | string | No | Upload to a specific workspace |
page_id | string | No | Existing page ID for re-upload (URL stays stable, version recorded) |
curl -X POST \
-H "Authorization: Bearer sd_..." \
-H "Content-Type: application/json" \
-d '{"object_key": "...", "upload_token": "...", "title": "Q4 Report", "visibility": "public"}' \
https://sharedrop.cloud/api/upload/finalize
Response 201:
{
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"slug": "abc123",
"title": "Q4 Report",
"mode": "static",
"file_size": 482190,
"visibility": "public",
"url": "/username/abc123",
"full_url": "https://sharedrop.cloud/username/abc123",
"created_at": "2026-04-07T00:00:00.000Z",
"updated_at": "2026-04-07T00:00:00.000Z"
}
}
Error Cases:
400 VALIDATION_ERROR-- Invalid body, unsupported file type, or a size mismatch402 TIER_LIMIT-- Kind not allowed on your plan (e.g. an image on Free)403 PAGE_LIMIT_REACHED-- Page count limit exceeded413 FILE_SIZE_EXCEEDED-- File exceeds the size limit for your plan
List Pages
GET /api/v1/pages
List your pages with cursor-based pagination.
Query Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
limit | number | 50 | Results per page (max 100) |
cursor | string | -- | Pagination cursor from previous response |
workspace_id | string | -- | Filter to a specific workspace |
curl -H "Authorization: Bearer sd_..." \
"https://sharedrop.cloud/api/v1/pages?limit=10"
Response 200:
{
"data": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"slug": "abc123",
"title": "My Report",
"mode": "static",
"file_size": 2048,
"visibility": "private",
"url": "/username/abc123",
"full_url": "https://sharedrop.cloud/username/abc123",
"created_at": "2026-04-07T00:00:00.000Z",
"updated_at": "2026-04-07T00:00:00.000Z"
}
],
"pagination": {
"next_cursor": "660e8400-e29b-41d4-a716-446655440001",
"has_more": true
}
}
To fetch the next page, pass cursor from pagination.next_cursor:
curl -H "Authorization: Bearer sd_..." \
"https://sharedrop.cloud/api/v1/pages?limit=10&cursor=660e8400-e29b-41d4-a716-446655440001"
Get Page
GET /api/v1/pages/:id
Get metadata for a specific page.
curl -H "Authorization: Bearer sd_..." \
https://sharedrop.cloud/api/v1/pages/550e8400-e29b-41d4-a716-446655440000
Response 200:
{
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"slug": "abc123",
"title": "My Report",
"mode": "static",
"file_size": 2048,
"visibility": "private",
"url": "/username/abc123",
"full_url": "https://sharedrop.cloud/username/abc123",
"created_at": "2026-04-07T00:00:00.000Z",
"updated_at": "2026-04-07T00:00:00.000Z"
}
}
Error Cases:
404 PAGE_NOT_FOUND-- Page does not exist or you don't have access
Fetch Page (raw content)
GET /api/v1/pages/:id/fetch
Mint a short-lived signed URL that returns a page's raw stored bytes — for an agent pulling a page's content into its context. This is the agent-native counterpart to a human download: it returns the original file with its real content type, never a zip and never the sandboxed viewer wrapper. Available on every tier (advertised as entitlements.fetch in the GET /api/v1/me response).
The mint response does not contain the bytes — it returns a fetch_url on the viewer origin that you then GET to stream the content. This mirrors the upload flow in reverse (mint → GET, like create_upload → PUT), so large pages never inflate the JSON response.
Access matches the rest of the API: the owner always may; a public page may be fetched by any authenticated caller; a shared/private page requires an active access grant matching one of your verified emails. Every denial returns 404.
# 1. Mint the fetch URL
curl -H "Authorization: Bearer sd_..." \
https://sharedrop.cloud/api/v1/pages/550e8400-e29b-41d4-a716-446655440000/fetch
Response 200:
{
"data": {
"fetch_url": "https://view.sharedrop.cloud/api/fetch/550e8400-e29b-41d4-a716-446655440000?token=...",
"expires_at": "2026-04-07T00:05:00.000Z",
"content_type": "text/html; charset=utf-8",
"mode": "static",
"size": 2048
}
}
# 2. Pull the raw bytes — no auth header, the URL token is the credential
curl "https://view.sharedrop.cloud/api/fetch/550e8400-...?token=..." -o page.html
The pull endpoint streams the bytes with Content-Disposition: attachment, X-Content-Type-Options: nosniff, and Content-Security-Policy: sandbox so the content can never execute or make network requests. The token is single-purpose and expires after ~5 minutes; an invalid, expired, or wrong-page token returns 404.
Error Cases:
401 UNAUTHORIZED-- Missing or invalid API key (mint endpoint)404 PAGE_NOT_FOUND-- Page does not exist or you don't have access; or an invalid/expired fetch token (pull endpoint)
Update Page
PATCH /api/v1/pages/:id
Update a page's title or visibility.
Request Body (JSON):
| Field | Type | Description |
|---|---|---|
title | string | New page title |
visibility | string | public, private, or shared |
Both fields are optional. Include only the fields you want to change.
curl -X PATCH \
-H "Authorization: Bearer sd_..." \
-H "Content-Type: application/json" \
-d '{"title": "Updated Title", "visibility": "public"}' \
https://sharedrop.cloud/api/v1/pages/550e8400-e29b-41d4-a716-446655440000
Response 200:
{
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"slug": "abc123",
"title": "Updated Title",
"mode": "static",
"file_size": 2048,
"visibility": "public",
"url": "/username/abc123",
"full_url": "https://sharedrop.cloud/username/abc123",
"created_at": "2026-04-07T00:00:00.000Z",
"updated_at": "2026-04-07T00:00:00.000Z"
}
}
Error Cases:
400 VALIDATION_ERROR-- Invalid JSON body or field values403 VALIDATION_ERROR-- Visibility not available on your plan (e.g., private on Free tier)404 PAGE_NOT_FOUND-- Page does not exist or you don't have access
Delete Page
DELETE /api/v1/pages/:id
Permanently delete a page and its stored HTML. This also deletes all versions, comments, shares, and access grants.
curl -X DELETE \
-H "Authorization: Bearer sd_..." \
https://sharedrop.cloud/api/v1/pages/550e8400-e29b-41d4-a716-446655440000
Response 200:
{
"data": {
"success": true
}
}
Error Cases:
404 PAGE_NOT_FOUND-- Page does not exist or you don't have access
Share Page
POST /api/v1/pages/:id/share
Share a page with someone by email address. Creates an access grant that allows the recipient to view the page.
Request Body (JSON):
| Field | Type | Required | Description |
|---|---|---|---|
email | string | Yes | Email address of the person to share with |
curl -X POST \
-H "Authorization: Bearer sd_..." \
-H "Content-Type: application/json" \
-d '{"email": "colleague@example.com"}' \
https://sharedrop.cloud/api/v1/pages/550e8400-e29b-41d4-a716-446655440000/share
Response 201:
{
"data": {
"id": "grant-uuid",
"email": "colleague@example.com",
"status": "pending",
"created_at": "2026-04-07T00:00:00.000Z"
}
}
The grant starts as pending. When the recipient signs in to sharedrop with a matching email, the grant automatically activates and they can view the page.
Error Cases:
400 VALIDATION_ERROR-- Invalid email address404 PAGE_NOT_FOUND-- Page does not exist or you don't have access