Authentication
Create a personal key under Settings → API keys. Send it on every request:
Authorization: Bearer srt_…
Firebase ID tokens also work for the dashboard. Scripts should use an srt_ key. Team keys need the Business plan.
Create a link
Custom slug is optional (3–32 letters, numbers, hyphens, or underscores). If you omit it, we assign a random path.
curl -X POST https://api.srt.to/api/links \
-H "Authorization: Bearer srt_YOUR_KEY" \
-H "Content-Type: application/json" \
-d "{\"longUrl\":\"https://example.com/page\",\"slug\":\"launch\"}"
Response 201:
{
"id": "…",
"slug": "launch",
"short_url": "https://srt.to/launch",
"long_url": "https://example.com/page"
}
Bulk import (JSON array, plan limit applies):
curl -X POST https://api.srt.to/api/links/bulk \
-H "Authorization: Bearer srt_YOUR_KEY" \
-H "Content-Type: application/json" \
-d "{\"links\":[{\"longUrl\":\"https://example.com/a\"},{\"longUrl\":\"https://example.com/b\"}]}"
Webhooks
Paid plans can register an HTTPS endpoint. On each click we POST:
{
"event": "click",
"timestamp": "2026-08-23T16:30:00.000Z",
"data": {
"link_id": "…",
"slug": "launch",
"country": "US",
"referrer": "https://t.co/",
"userAgent": "Mozilla/5.0 …"
}
}
Verify the request with header X-Srt-Signature — it matches the secret returned when you created the webhook.
curl -X POST https://api.srt.to/api/webhooks \
-H "Authorization: Bearer srt_YOUR_KEY" \
-H "Content-Type: application/json" \
-d "{\"url\":\"https://example.com/hooks/srt\",\"events\":[\"click\"]}"
Errors & limits
Failures return { "error": "…" } with 400, 401, 403, 409, or 429.
- Create: 20 requests / minute / IP
- Bulk: 5 requests / minute / IP
- Free plan: 1,000 API requests, 2 requests / 10 seconds
- Paid plans raise those caps
Endpoint reference
| Method | Path | What it does |
|---|---|---|
| GET | /api/links | List links (search, sort, tags) |
| POST | /api/links | Create a short link |
| GET | /api/links/:id | Get one link |
| PATCH | /api/links/:id | Edit destination, title, tags |
| DELETE | /api/links/:id | Delete a link |
| GET | /api/links/:id/qr | QR SVG (?format=svg) |
| POST | /api/links/bulk | Batch create |
| GET | /api/analytics/aggregate | All-link stats (?range=30d) |
| GET | /api/analytics/:id/stats | Per-link click stats |
| GET | /api/overview | Dashboard totals |
| GET / POST | /api/domains | Custom domains |
| POST | /api/domains/:id/verify | Verify DNS |
| GET / POST / DELETE | /api/keys | API keys |
| GET / POST / DELETE | /api/webhooks | Click webhooks |
| GET / POST | /api/utm/presets | UTM presets |
| GET / POST | /api/workspaces | Team workspaces |
| GET / POST / DELETE | /api/workspaces/:id/members | Invite by email |
| GET / PUT | /api/bio | Your link-in-bio page |
| GET | /api/bio/public/:handle | Published bio (no auth) |
| GET | /api/billing/plans | Plan catalog |
Create a key, then try the curl above. Questions: use Settings in the app, or report abuse for public-link issues.