— documentation
Disposable Clipboard API Reference
FastPaste provides a disposable clipboard API for one-time code sharing and secure temporary file sharing at /api/v1/. All requests require a Bearer token. Responses are JSON, and files are base64-encoded in the response body.
View API pricing plans · Open secure temporary file sharing app
// 02a
Web UI vs API
| Web UI | API (this reference) | |
|---|---|---|
| Base path | /api/clip | /api/v1/clip |
| Auth | Optional magic link (free tier) | Bearer API key (required) |
| Rate limit | 10 req/min per IP | Daily plan quota |
| TTL | 10 min default; Personal can extend | 1 h (Starter) or 24 h (Pro) |
| Multi-read | Web push only (readMode / maxReads) | Single pull per code |
Specialized viewers (JSON, Redact, Agent, diff, logs, …) use the web push flow at /api/json, /api/redact, etc. — not the v1 API.
// 01
Authentication
Every request must include an Authorization header with your API key as a Bearer token. Keys are 40-character hex strings provisioned when you purchase a plan.
Authorization: Bearer a3f1c8e2d94b07651af2...
Missing or invalid keys return 401 Unauthorized.
Passphrase-protected clips also use x-clip-passphrase on pull requests.
// 02
Plans
| API Starter | Pro | |
|---|---|---|
| Max file size (per upload) | 10 MB | 100 MB |
| Requests / day | 1,000 | Unlimited |
| Content TTL | 1 hour | 24 hours |
Daily quota is consumed on successful push/pull operations. Remaining quota is returned as requests_remaining and the X-Requests-Remaining header. Quota resets at UTC midnight.
// 02b
Zero-knowledge text sharing
The web UI defaults to Sensitive mode for text pushes. Content is encrypted in the browser with AES-GCM before it reaches the server. Only ciphertext is stored — the server never sees your plaintext.
The recipient needs both the 6-digit code and the passphrase you shared separately. On pull, send the passphrase in the x-clip-passphrase header (API) or enter it in the web UI.
// Browser encrypts before POST
{
"text": "<base64 ciphertext>",
"clientEncrypted": true,
"ttlSeconds": 600
}
// Passphrase is never sent to the server — only used locally for AES-GCM.Quick mode skips client encryption and stores plaintext on the server (still burn-after-read). Optional server-side passphrase protection locks the code but does not hide content from the server.
// 02c
One-time link sharing
The web UI can deliver a one-time link instead of a bare 6-digit code. Links look like https://fastpaste.dev/?code=482193#- with an optional secret after the #- prefix.
The fragment (after #) is never sent to the server and is omitted by most chat link previews — reducing accidental burns from Slack or iMessage unfurl bots. Sensitive mode embeds the decryption passphrase in the fragment; quick mode can embed an optional server-side pull passphrase.
https://fastpaste.dev/?code=482193#-my-passphrase
// 02d
CLI (from source)
The repo ships cli/fastpaste.mjs for push/pull against the v1 API. It is not published to npm yet — clone the repo or link the binary locally.
git clone https://github.com/tiderbrandt/fastpaste.git cd fastpaste export FASTPASTE_API_KEY=your_key node cli/fastpaste.mjs push "hello world" node cli/fastpaste.mjs pull 482193 node cli/fastpaste.mjs pull 482193 --passphrase "secret" node cli/fastpaste.mjs push --file ./report.pdf
// 02e
AI agents & MCP
Run npm run mcp from a clone with FASTPASTE_API_KEY set (or add mcp/server.mjs to Cursor). MCP tools:
| Tool | Purpose |
|---|---|
| share_secret | Push text once; returns a 6-digit code |
| share_agent_handoff | Push secret + agent prompt + constraints |
| retrieve_secret | Pull by code; text, file, or structured JSON |
Guide: share secrets with AI agents. UI: Agent Handoff.
{
"mcpServers": {
"fastpaste": {
"command": "node",
"args": ["/path/to/fastpaste/mcp/server.mjs"],
"env": { "FASTPASTE_API_KEY": "your_key" }
}
}
}// 02f
POST /api/v1/agent-handoff
Same clip type as the /agent tool. Pull returns type: agent_handoff with secret, agentPrompt, and constraints. Use {{CODE}} in agentPrompt as a placeholder.
curl -X POST https://fastpaste.dev/api/v1/agent-handoff \
-H "Authorization: Bearer <key>" \
-H "Content-Type: application/json" \
-d '{
"title": "Deploy token",
"agentPrompt": "Pull FastPaste code {{CODE}} with retrieve_secret.",
"constraints": ["Do not echo the secret in chat"],
"secret": "sk-live-..."
}'// 03
POST /api/v1/clip — push content
Text
curl -X POST https://fastpaste.dev/api/v1/clip \
-H "Authorization: Bearer <key>" \
-H "Content-Type: application/json" \
-d '{"text": "hello world", "passphrase": "optional-secret", "webhook_url": "https://example.com/hooks/fastpaste"}'File
curl -X POST https://fastpaste.dev/api/v1/clip \ -H "Authorization: Bearer <key>" \ -F "file=@/path/to/report.pdf" -F "passphrase=optional-secret" \ -F "webhook_url=https://example.com/hooks/fastpaste"
Response 201
{
"code": "482193",
"expires_in": 3600,
"plan": "developer",
"requests_remaining": 999,
"passphrase_protected": true
}Text limits are enforced on UTF-8 byte length, not character count.
| Field | Type | Description |
|---|---|---|
| text | string | Required for JSON push |
| passphrase | string | Optional server-side pull lock (min 4 chars) |
| webhook_url | string | Optional HTTPS URL — POST on first pull (see Webhooks) |
| code | string | 6-digit retrieval code (response) |
| expires_in | number | Seconds until the code expires (response) |
| requests_remaining | number | Remaining quota today (response) |
// 03b
Webhooks on pull
Pass webhook_url on POST /api/v1/clip (JSON or multipart). When the clip is first pulled, FastPaste POSTs once to your URL and then forgets it.
{
"event": "clip.opened",
"code": "482193",
"type": "text",
"opened_at": "2026-06-24T12:00:00.000Z"
}Must be http:// or https://. Web UI pushes can also set webhook_url on POST /api/clip. Guide: webhooks on pull.
// 04
GET /api/v1/clip/:code — pull content
Retrieves and permanently deletes the clip in one atomic operation. There is no second retrieval.
curl https://fastpaste.dev/api/v1/clip/482193 -H "Authorization: Bearer <key>" -H "x-clip-passphrase: optional-secret"
Response 200 — sensitive (encrypted)
{
"type": "text",
"clientEncrypted": true,
"data": "{\"v\":1,\"ciphertext\":\"...\", ...}"
}Decrypt data with the passphrase (CLI: --passphrase; MCP: passphrase arg). Structured tool clips return their own type (e.g. agent_handoff, redacted).
Response 200 — large file
{
"type": "file",
"download_url": "/api/clip/482193/download",
"download_token": "<one-time token>",
"mimeType": "application/pdf",
"file_name": "report.pdf"
}Fetch the file with GET download_url and header x-clip-download-token.
Response 200 — text
{
"type": "text",
"data": "hello world",
"createdAt": 1746876000000
}Response 200 — file
{
"type": "image",
"data": "<base64-encoded content>",
"mimeType": "image/png",
"createdAt": 1746876000000
}| Field | Description |
|---|---|
| type | text | image | pdf | file |
| data | Raw text, or base64-encoded binary for files |
| mimeType | MIME type of the file (omitted for text) |
| createdAt | Unix timestamp (ms) when the clip was created |
// 05
GET /api/clip/:code/receipt — web read receipt
This endpoint is for the web clipboard flow (not API-key flow). It returns whether a clip has been opened, but requires a receipt token from the original web push response to prevent code enumeration.
Push response field
{
"code": "482193",
"expires_in": 600,
"receipt_token": "3f2f4b6c0f9946f8ac8cc5f11e72adf7"
}Receipt request
curl https://fastpaste.dev/api/clip/482193/receipt -H "x-clip-receipt-token: 3f2f4b6c0f9946f8ac8cc5f11e72adf7"
Response 200
{
"opened": false,
"pending": true
}| Field | Description |
|---|---|
| opened | true once the clip has been consumed |
| pending | true while the clip still exists and is unread |
| Status | Meaning |
|---|---|
| 200 | Receipt status returned |
| 400 | Invalid code format |
| 404 | Invalid or missing receipt token (or code not found) |
| 429 | Rate limited |
// 06
Errors
| Status | Meaning |
|---|---|
| 400 | Bad request — invalid code format or missing body field |
| 401 | Invalid/missing API key, or passphrase required for protected clip |
| 403 | Invalid passphrase for protected clip |
| 404 | Code not found or already retrieved (burned) |
| 413 | Content too large for your plan |
| 415 | Unsupported file type |
| 429 | Daily request limit reached — resets at UTC midnight |
| 500 | Server error |
Error body
{ "error": "Human-readable description" }// 07
Supported file formats
SVG is permanently blocked — SVG files can embed <script> tags that execute in the browser. All other validation is server-side against a hardcoded MIME type allowlist; filename extensions are ignored.
| Category | Formats |
|---|---|
| Images | JPEG, PNG, GIF, WebP, AVIF, BMP, TIFF |
| Documents — Office | PDF, DOCX, XLSX, PPTX, DOC, XLS, PPT |
| Documents — OpenDocument | ODT, ODS, ODP |
| eBooks | EPUB |
| Archives | ZIP, GZ, 7Z, TAR, RAR |
| Text | TXT, CSV, Markdown |
| Audio | MP3, WAV, OGG, AAC, FLAC |
| Video | MP4, WebM, MOV |
| Fonts | TTF, OTF, WOFF, WOFF2 |