API Reference¶
All endpoints accept and return raw text or JSON. No authentication required for public pastes.
Create Paste¶
Headers¶
| Header | Required | Description |
|---|---|---|
X-Slug |
No | Custom slug (random if not provided) |
X-Private |
No | Set to true for private paste |
X-Lang |
No | Language for syntax highlighting |
Body¶
Raw text content of the paste.
Response: 201 Created¶
For private pastes:
Response: 409 Conflict¶
Response: 403 Forbidden¶
Returned when X-Private: true is sent but the server has no PRIVATE_USER/PRIVATE_PASS configured.
Examples¶
# Create paste
curl -X POST https://paste.semi.sh/api/paste -d "hello world"
# With custom slug
curl -X POST https://paste.semi.sh/api/paste \
-H "X-Slug: mycode" \
-d "content here"
# Private paste
curl -X POST https://paste.semi.sh/api/paste \
-H "X-Private: true" \
-H "X-Lang: go" \
-d "package main"
# From file
curl -X POST https://paste.semi.sh/api/paste \
-H "X-Slug: deploy" \
-H "X-Lang: bash" \
--data-binary @deploy.sh
Overwrite Paste¶
Replaces the content of an existing paste. For private pastes, requires Basic Auth.
Response: 200 OK¶
Response: 401 Unauthorized¶
Examples¶
# Overwrite public paste
curl -X PUT https://paste.semi.sh/api/paste/mycode -d "updated content"
# Overwrite private paste (requires auth)
curl -X PUT -u admin:secret https://paste.semi.sh/api/paste/secrets -d "new secrets"
List Pastes¶
Returns metadata for all public and private pastes. Requires admin auth (PRIVATE_USER/PRIVATE_PASS via HTTP Basic Auth).
Response: 200 OK¶
{
"public": [
{
"slug": "abc123",
"private": false,
"lang": "go",
"created_at": "2026-06-30T12:00:00Z",
"size": 11,
"ttl": "never"
}
],
"private": [
{
"slug": "secrets",
"private": true,
"lang": "",
"created_at": "2026-06-30T12:01:00Z",
"size": 7,
"ttl": "never"
}
]
}
Each entry mirrors the models.Paste fields. An empty scope returns [].
Response: 401 Unauthorized¶
Response: 403 Forbidden¶
Returned when admin auth is not configured on the server. See private_auth_not_configured.
Examples¶
Delete Paste¶
Removes a paste from the scope indicated by the X-Private header. Requires admin auth. A slug that exists in both scopes must be deleted twice (once per scope). Idempotent: deleting a missing paste returns 200.
Headers¶
| Header | Required | Description |
|---|---|---|
X-Private |
No | Set to true to delete from the private scope (default: public) |
Response: 200 OK¶
Response: 401 Unauthorized¶
Examples¶
# Delete public paste
curl -X DELETE -u admin:secret https://paste.semi.sh/api/paste/mycode
# Delete private paste
curl -X DELETE -u admin:secret -H "X-Private: true" https://paste.semi.sh/api/paste/secrets
Get Public Paste¶
Browser (HTML)¶
Returns an HTML page with syntax highlighting (dark theme). The User-Agent header is checked to determine if the request is from a browser.
curl / tools (raw text)¶
Returns raw text with Content-Type: text/plain.
Force raw text¶
Always returns raw text regardless of User-Agent.
Response: 200 OK¶
Browser: Content-Type: text/html
curl: Content-Type: text/plain; charset=utf-8
Response: 404 Not Found¶
Paste does not exist or is private.
Examples¶
# Browser: HTML with syntax highlighting
curl -s https://paste.semi.sh/abc123 | head
# Force raw text
curl -s https://paste.semi.sh/abc123?raw=1
Get Private Paste¶
Returns HTML with syntax highlighting for browsers, raw text for curl/tools. Requires HTTP Basic Auth.
Browser (HTML)¶
Returns an HTML page with syntax highlighting (dark theme). The User-Agent header is checked to determine if the request is from a browser.
curl / tools (raw text)¶
Returns raw text with Content-Type: text/plain.
Force raw text¶
Always returns raw text regardless of User-Agent.
Response: 200 OK¶
Browser: Content-Type: text/html
curl: Content-Type: text/plain; charset=utf-8
Response: 401 Unauthorized¶
Examples¶
# Browser: HTML with syntax highlighting (prompts for credentials)
curl -u admin:secret https://paste.semi.sh/private/secrets
# Force raw text
curl -u admin:secret https://paste.semi.sh/private/secrets?raw=1
Health Check¶
Response: 200 OK¶
Examples¶
Landing Page¶
Returns a minimal HTML page with usage instructions and a link to the source repository.
Error Responses¶
All errors return JSON with an error field:
| Status | Error | Cause |
|---|---|---|
| 400 | invalid_slug |
Slug contains invalid characters or is reserved |
| 401 | (empty) | Missing or invalid admin auth (private paste access, list, delete) |
| 403 | private_auth_not_configured |
Private paste / admin action requested but server has no auth |
| 404 | (empty) | Paste not found |
| 409 | slug_exists |
Slug already in use in the same scope (public or private) |
| 413 | (empty) | Paste exceeds 10 MB limit |
| 500 | (empty) | Server error |
Slug Validation¶
Slugs must:
- Be 1-64 characters long
- Contain only
[a-zA-Z0-9_-] - Not be a reserved word:
private,api,health - Not contain path traversal sequences (
..,/,\)