Files
palette/docs/API.md
T
poslop cd70dd0b0e
CI / test (push) Failing after 6s
CI / docker (push) Skipped
Merge origin/main (license, compose, #65 leak guard) into cans work
2026-09-09 16:39:14 -05:00

4.1 KiB

Palette API

All endpoints are JSON unless noted. The web UI is served from the same port.

Create paste

curl -X POST http://localhost:8080/api/pastes \
  -H "Content-Type: application/json" \
  -d '{
    "content": "print(hello)",
    "title": "my snippet",
    "language": "python",
    "expires_in": "168h",
    "password": "optional",
    "custom_slug": "optional",
    "burn_after_read": false,
    "burn_after_reads": 1,
    "visibility": "public"
  }'
  • expires_in is a Go duration string (90m, 6h, 336h). Omit for no expiry.
  • visibility is public or unlisted.
  • Alternatively (or additionally), public may be sent as a boolean (#83): false maps to unlisted and true maps to public. When both fields are present, the boolean public takes precedence over the string visibility. Omitting both defaults to public.
  • burn_after_reads sets how many reads the paste survives (default 1 when burn_after_read is true). A read is counted per unique viewer session; the same viewer returning within 15 minutes does not count again.
  • Response includes id, url, raw_url, api_url, expires_at, created_at, and a one-time deletion_token.

Errors: 400 invalid body/content too large/duplicate slug, 401 password required, 404 paste expired/burned/gone, 413 content exceeds max bytes, 429 rate limited.

Get paste

curl http://localhost:8080/api/pastes/{id}
# password-protected pastes:
curl "http://localhost:8080/api/pastes/{id}?password=secret"
# or via header: X-Paste-Password: secret

The response includes reads_remaining (null when no read budget is set).

Raw content

curl http://localhost:8080/raw/{id}

Raw reads count against a burn-after-read budget, same as page views.

Delete

# soft delete (requires the deletion token from the create response)
curl -X DELETE -H "Authorization: Bearer TOKEN" http://localhost:8080/api/pastes/{id}
# ...or via query param; the creator browser (viewer cookie) may also delete without a token
curl -X DELETE "http://localhost:8080/api/pastes/{id}?token=TOKEN"

# hard delete immediately (requires the one-time deletion token)
curl -X DELETE "http://localhost:8080/api/pastes/{id}/redeem?token=TOKEN"

Lists

curl "http://localhost:8080/api/public?limit=25&offset=0"   # public history
curl http://localhost:8080/api/mine                          # this browser's pastes (viewer cookie)

Language detection

curl -X POST http://localhost:8080/api/guess-language \
  -H "Content-Type: application/json" \
  -d '{"content": "package main"}'

Cans (bundles of items)

A can bundles multiple text items (and files) into one shareable page at /can/{id}. Password, expiry, visibility, custom slug, and viewer-scoped deletion work exactly like pastes; cans appear as normal rows (with a can badge) in /api/public and /api/mine.

curl -X POST http://localhost:8080/api/pastes/can \
  -F "title=My bundle" \
  -F "expires_in=48h" \
  -F "custom_slug=my-bundle" \
  -F 'json_items=[{"title":"notes.txt","content":"some notes"}]' \
  -F "files=@screenshot.png" \
  -F "files=@log.txt"

curl http://localhost:8080/api/cans/{id}
curl http://localhost:8080/api/cans/{id}/items/{item_id}
curl -X DELETE http://localhost:8080/api/cans/{id}   # creator browser only (vwr cookie)

Password-protected cans use the same unlock flow as pastes: POST /can/{id} with the password sets an HMAC-bound cookie; item fetches accept the cookie as well as the X-Paste-Password header / ?password= query param.

Web pages

  • /new — create a paste
  • /history — public paste history
  • /mine — pastes created from this browser
  • /{id} — view a paste
  • /unlock/{id} — password gate for protected pastes
  • /raw/{id} — raw content with original content type

Expiry and deletion

  • Expired pastes are soft-deleted by a background sweeper (runs every minute).
  • Soft-deleted pastes are hard-deleted after a 7-day grace period.
  • Deletion tokens allow immediate hard delete.
  • Burn-after-read pastes are soft-deleted once the read budget is exhausted.