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

HeaderDescription
X-RateLimit-LimitMaximum requests allowed in the current window
X-RateLimit-RemainingRequests remaining in the current window
X-RateLimit-ResetUnix timestamp when the window resets

Limits by Tier

EndpointFreeProTeam
Upload20/min100/min200/min
List / Read / Update60/min300/min600/min
Delete / Share30/min150/min300/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

CodeHTTP StatusDescription
UNAUTHORIZED401Invalid or missing API key
RATE_LIMIT_EXCEEDED429Too many requests. Check X-RateLimit-* headers.
PAGE_NOT_FOUND404Page does not exist or you don't have access
VALIDATION_ERROR400Invalid request body or parameters
PAGE_LIMIT_REACHED403Page count limit exceeded for your plan
FILE_SIZE_EXCEEDED413File 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):

FieldTypeRequiredDescription
filenamestringYesFilename including extension (e.g. report.pdf)
content_typestringYesMIME type (e.g. application/pdf)
size_bytesnumberYesExact body size in bytes — must match the Content-Length of the PUT
workspace_idstringNoUpload 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):

FieldTypeRequiredDescription
object_keystringYesThe object_key returned by step 1
upload_tokenstringYesThe upload_token returned by step 1
titlestringNoPage title. Defaults to the document title (HTML/PDF) or filename stem
visibilitystringNoprivate (default), shared, or public
modestringNoHTML only: static or interactive (default: your account's default upload mode, initially interactive; configure in Settings). Ignored for non-HTML kinds
workspace_idstringNoUpload to a specific workspace
page_idstringNoExisting 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 mismatch
  • 402 TIER_LIMIT -- Kind not allowed on your plan (e.g. an image on Free)
  • 403 PAGE_LIMIT_REACHED -- Page count limit exceeded
  • 413 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:

ParameterTypeDefaultDescription
limitnumber50Results per page (max 100)
cursorstring--Pagination cursor from previous response
workspace_idstring--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_uploadPUT), 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):

FieldTypeDescription
titlestringNew page title
visibilitystringpublic, 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 values
  • 403 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):

FieldTypeRequiredDescription
emailstringYesEmail 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 address
  • 404 PAGE_NOT_FOUND -- Page does not exist or you don't have access