API
Programmatic access to cuts.bz. The API is JSON-only and intentionally tiny: shorten a URL, follow a redirect, manage settings.
Authentication & rate limit
The public endpoints accept three classes of caller:
- Anonymous — allowed, but limited to one new link per
5seconds per source IP. - Whitelisted IP — bypass the rate limit. Configured in settings → IP whitelist (stored in SQLite).
- Token — bypass the rate limit by sending the token in the JSON body as
"token": "<value>". Tokens are 60–120 chars, optionally tied to an expiration date and a description. Stored in SQLite and managed in settings → API tokens.
The source IP is taken from X-Forwarded-For (first hop) with X-Real-IP as fallback. Caddy in the docker-compose stack sets these headers.
Shorten a URL
Request body
| Field | Type | Required | Description |
|---|---|---|---|
url | string | yes | HTTP/HTTPS URL to shorten. Validated as a real URL with a hostname. |
ttl | int | no | Lifetime in seconds. If omitted or equal to the build default (259200), the link gets the system default from settings. |
token | string | no | Optional API token to bypass the per-IP rate limit. |
Response
{
"result_boolean": true,
"result": "https://cuts.bz/9",
"describe": "Anonymous request - Ok, TTL = 259200",
"replay_at": 1777465987.6721976
}
Example
curl -X POST https://cuts.bz/ \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com/very/long/path"}'
With a token
curl -X POST https://cuts.bz/ \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/page",
"token": "<your-60-to-120-char-token>",
"ttl": 86400
}'
Resolve a short link
Returns 307 Temporary Redirect to the original URL. If the slug is unknown, expired, or has run out of clicks, redirects to the landing page (302 Found → /).
Each successful follow records a click row (timestamp, source IP, user-agent, referer) used by the analytics screen.
$ curl -sI https://cuts.bz/9
HTTP/1.1 307 Temporary Redirect
location: https://example.com/very/long/path
Errors
| HTTP | Body | When |
|---|---|---|
200 | { result_boolean: false, describe: "Too many requests from …" } | Anonymous caller hit the per-IP cooldown. |
422 | FastAPI validation error | Body is not JSON, missing url, or url is not a valid HTTP/HTTPS URL. |
302 | Location: / | Slug unknown, expired, or out of clicks. |
Quick recipes
Disposable token for a CI job
Generate a token with a short expiration (e.g. 7 days) in settings, add a description like ci/release-notes, paste it into the job environment, and let it expire on its own.
Bulk shortening
cat urls.txt | while read u; do
curl -s -X POST https://cuts.bz/ \
-H "Content-Type: application/json" \
-d "$(jq -nc --arg u "$u" --arg t "$TOKEN" '{url:$u, token:$t}')" \
| jq -r .result
done