README rework: user-first structure, features, screenshots, config table; API detail moved to docs/API.md (#47)
This commit is contained in:
+107
@@ -0,0 +1,107 @@
|
||||
# Palette API
|
||||
|
||||
All endpoints are JSON unless noted. The web UI is served from the same port.
|
||||
|
||||
## Create paste
|
||||
|
||||
```bash
|
||||
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`.
|
||||
- `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
|
||||
|
||||
```bash
|
||||
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
|
||||
|
||||
```bash
|
||||
curl http://localhost:8080/raw/{id}
|
||||
```
|
||||
|
||||
Raw reads count against a burn-after-read budget, same as page views.
|
||||
|
||||
## Delete
|
||||
|
||||
```bash
|
||||
# soft delete (creator browser only; plain API clients unaffected)
|
||||
curl -X DELETE http://localhost:8080/api/pastes/{id}
|
||||
|
||||
# hard delete immediately (requires the one-time deletion token)
|
||||
curl -X DELETE "http://localhost:8080/api/pastes/{id}/redeem?token=TOKEN"
|
||||
```
|
||||
|
||||
## Lists
|
||||
|
||||
```bash
|
||||
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
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8080/api/guess-language \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"content": "package main"}'
|
||||
```
|
||||
|
||||
## Cans (bundles of items)
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8080/api/pastes/can \
|
||||
-F "title=My bundle" \
|
||||
-F "expires_in=48h" \
|
||||
-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}
|
||||
```
|
||||
|
||||
## 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.
|
||||
Reference in New Issue
Block a user