⚡LinkBolt

API

All endpoints live under https://linkbolt-jet.vercel.app/api/v1, take and return JSON, and need an API key from settings. Limits: 120 requests per minute per key.

Authentication

Authorization: Bearer lb_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

A missing or unknown key returns 401. Over the limit returns 429 with a retryAfter field in seconds.

Create a link

POST /api/v1/links
{
  "url": "https://example.com/very/long/path",   // required
  "slug": "launch",                              // optional, 3–32 chars [a-zA-Z0-9_-]
  "title": "Launch post",                        // optional
  "expiresAt": "2026-12-31T23:59:00Z",           // optional ISO date
  "publicStats": false                           // optional
}

201 →
{
  "id": "…", "slug": "launch", "shortUrl": "https://linkbolt-jet.vercel.app/launch",
  "url": "https://example.com/very/long/path", "title": "Launch post",
  "clicks": 0, "publicStats": false, "expiresAt": "…", "createdAt": "…", "updatedAt": "…"
}

400 invalid url / slug · 409 slug already taken

List, read, update, delete

GET    /api/v1/links              → { "links": [ … ] }
GET    /api/v1/links/:slug        → link
PATCH  /api/v1/links/:slug        { "url"?, "title"?, "expiresAt"?, "publicStats"? } → link
DELETE /api/v1/links/:slug        → 204

Stats

GET /api/v1/links/:slug/stats?days=30     (1–90)

{
  "slug": "launch", "days": 30,
  "total": 1240, "humans": 1180, "bots": 60, "uniques": 902,
  "byDay":     [ { "day": "2026-09-01", "clicks": 41 }, … ],
  "referrers": [ { "name": "twitter.com", "clicks": 512 }, { "name": "Direct", "clicks": 300 } ],
  "countries": [ { "name": "NG", "clicks": 640 }, … ],
  "devices":   [ { "name": "mobile", "clicks": 800 }, … ],
  "browsers":  [ { "name": "Chrome", "clicks": 700 }, … ]
}

Bots are detected from the user agent and excluded from every breakdown. Uniques are counted from a daily salted hash of IP and user agent, so the same visitor counts once per day and no IP is ever stored.

Public endpoints

GET /:slug                         302 → destination (410 if expired, 404 if unknown)
GET /api/qr/:slug?format=svg|png&size=320
POST /api/shorten { "url" }        anonymous, 10 per hour per IP, links expire in 7 days
GET /api/health

Example

curl -s -X POST https://linkbolt-jet.vercel.app/api/v1/links \
  -H "Authorization: Bearer $LINKBOLT_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://github.com/scholasticstan/linkbolt","slug":"src"}' | jq .shortUrl