๐Ÿ‘ป API Reference

REST API for Ghostclip.dev โ€” ephemeral encrypted clipboard for developers and AI agents.

Rate limit
100req/day
Max TTL
24hours
Max size
128KB
OpenAPI spec

Authentication

All API endpoints require a Bearer token in the Authorization header. Get your key at ghostclip.dev/mcp.

Authorization: Bearer gc_your_api_key_here

Rate limit headers

Every API response includes these headers:

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 99
X-RateLimit-Reset: 1711234567   # Unix timestamp when the window resets
Retry-After: 3600               # Only on 429 responses

Endpoints

POST/api/v1/clipboard

Create an encrypted clipboard. Returns the access code and expiry.

Body fieldTypeDescription
contentstring*Text to store (max 128 KB)
ttl_minutesintTime-to-live in minutes (1โ€“1440). Default: 60
max_viewsintAuto-delete after N reads (0 = unlimited). Default: 0
curl -X POST https://ghostclip.dev/api/v1/clipboard \
  -H "Authorization: Bearer gc_..." \
  -H "Content-Type: application/json" \
  -d '{"content": "Hello!", "ttl_minutes": 30}'

# โ†’ {"code": "swift green orbit", "url": "https://ghostclip.dev/...", "expires_at": "..."}
GET/api/v1/clipboard/{code}

Read clipboard content. The code is URL-encoded (spaces โ†’ %20).

curl "https://ghostclip.dev/api/v1/clipboard/swift%20green%20orbit" \
  -H "Authorization: Bearer gc_..."

# โ†’ {"content": "Hello!", "expires_at": "...", "views_remaining": null, ...}
PUT/api/v1/clipboard/{code}

Replace clipboard content. TTL and max_views are not changed.

curl -X PUT "https://ghostclip.dev/api/v1/clipboard/swift%20green%20orbit" \
  -H "Authorization: Bearer gc_..." \
  -H "Content-Type: application/json" \
  -d '{"content": "Updated!"}'

# โ†’ {"ok": true}
DELETE/api/v1/clipboard/{code}

Delete a clipboard immediately before it expires.

curl -X DELETE "https://ghostclip.dev/api/v1/clipboard/swift%20green%20orbit" \
  -H "Authorization: Bearer gc_..."

# โ†’ {"ok": true}
GET/api/v1/words

Generate a random access code without creating a clipboard. Query param: n (3 or 4 words).

curl "https://ghostclip.dev/api/v1/words?n=3" \
  -H "Authorization: Bearer gc_..."

# โ†’ {"code": "amber forest pine", "words": ["amber", "forest", "pine"]}

MCP server

No local install. The MCP server runs on Ghostclip.dev. Add the URL and your API key to your client config. See the MCP guide.
POST/api/mcp

JSON-RPC 2.0 endpoint (MCP Streamable HTTP transport, spec 2024-11-05). Tools: create_clipboard, read_clipboard, update_clipboard, delete_clipboard, generate_code.

Error responses

All errors return JSON with an error field:

{"error": "Clipboard not found or expired"}
Status Meaning
400Invalid input (bad code format, null bytes, content too large)
401Missing, invalid, disabled, or expired API key
404Clipboard not found or expired
410View limit reached โ€” clipboard auto-deleted
429Rate limit exceeded โ€” check Retry-After header
503Service temporarily unavailable

Code examples

Create + read + delete

API_KEY="gc_your_key"

# Create
CODE=$(curl -sX POST https://ghostclip.dev/api/v1/clipboard \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"content":"Hello!","ttl_minutes":60}' | python3 -c "import sys,json; print(json.load(sys.stdin)['code'])")

echo "Code: $CODE"

# Read
curl -s "https://ghostclip.dev/api/v1/clipboard/$(python3 -c "from urllib.parse import quote; print(quote('$CODE'))")" \
  -H "Authorization: Bearer $API_KEY"

# Delete
curl -sX DELETE "https://ghostclip.dev/api/v1/clipboard/$(python3 -c "from urllib.parse import quote; print(quote('$CODE'))")" \
  -H "Authorization: Bearer $API_KEY"

Using the official Python SDK

pip install ghostclip
from ghostclip import GhostclipClient, GhostclipNotFoundError, GhostclipRateLimitError

gc = GhostclipClient(api_key="gc_your_key")

# Create
clip = gc.create("Hello from Python!", ttl_minutes=30)
print(clip.code)   # "swift green orbit"

# Read
try:
    result = gc.read(clip.code)
    print(result.content)
except GhostclipNotFoundError:
    print("Expired or not found")
except GhostclipRateLimitError as e:
    print(f"Rate limit hit โ€” retry in {e.retry_after}s")

# Check rate limit
if gc.rate_limit:
    print(f"{gc.rate_limit.remaining}/{gc.rate_limit.limit} requests remaining")

# Delete
gc.delete(clip.code)

Using fetch (no dependencies)

const API_KEY = "gc_your_key";
const BASE    = "https://ghostclip.dev";

async function createClipboard(content, ttlMinutes = 60) {
  const res = await fetch(`${BASE}/api/v1/clipboard`, {
    method: "POST",
    headers: { "Authorization": `Bearer ${API_KEY}`, "Content-Type": "application/json" },
    body: JSON.stringify({ content, ttl_minutes: ttlMinutes }),
  });
  if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
  return res.json();
}

async function readClipboard(code) {
  const res = await fetch(`${BASE}/api/v1/clipboard/${encodeURIComponent(code)}`, {
    headers: { "Authorization": `Bearer ${API_KEY}` },
  });
  if (res.status === 404 || res.status === 410) throw new Error("Not found or expired");
  if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
  return res.json();
}

// Example
const clip = await createClipboard("Hello from JS!", 30);
console.log(clip.code);
const { content } = await readClipboard(clip.code);
console.log(content);

Resources

Buy Me a Coffee at ko-fi.com