REST API for creating short links, reading analytics, generating QR codes and managing your account. Every response is JSON: {"ok": true, "data": …} on success, {"ok": false, "error": "…"} on failure.
Create an API key in your dashboard → API keys. Send it on every request as a Bearer token (preferred) or as the ?api_key= query parameter.
Authorization: Bearer YOUR_API_KEY
Paste your key below to use the live try-it console. It is stored only in this browser's local storage.
Each key has its own per-minute limit (default 60, shown in the X-RateLimit-Limit / X-RateLimit-Remaining headers; 429 when exceeded). API access requires the Pro or Business plan, and custom aliases additionally require a plan with the custom-alias feature — otherwise the API returns 403.
| Method | Path | Description | Parameters |
|---|---|---|---|
| POST | /api/v1/links |
Create a short link | url (required), alias, title, description, password, expires_at, max_clicks, redirect_type |
| GET | /api/v1/links |
List your links (paginated) | page, per_page (max 100), search |
| GET | /api/v1/links/{id} |
Get one link | — |
| PUT | /api/v1/links/{id} |
Update a link | destination/url, alias, title, description, redirect_type, is_active, password, expires_at, max_clicks |
| DELETE | /api/v1/links/{id} |
Delete a link | — |
| GET | /api/v1/analytics |
Account analytics overview | — |
| GET | /api/v1/analytics/{id} |
Per-link analytics | — |
| POST | /api/v1/qr |
QR code for a link (client-side snippet) | link_id (required), size, ec_level, fg, bg |
| GET | /api/v1/account |
Account, plan and usage | — |
POST /api/v1/qr does not return a server-side PNG — SwiftLink ships no server-side QR renderer. It returns the short URL plus a ready-to-paste client-side snippet that renders a crisp SVG QR with the bundled MIT-licensed qrcode.js library. Nothing is faked; the response field server_side is false.Fires real fetch() requests against this installation's /api/v1/* endpoints using your saved key.
// response appears here
# Create a link
curl -X POST "https://YOUR-DOMAIN/api/v1/links" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com/some/long/page","alias":"launch-2026","title":"Launch page"}'
# List links (page 2, 10 per page)
curl "https://YOUR-DOMAIN/api/v1/links?page=2&per_page=10" \
-H "Authorization: Bearer YOUR_API_KEY"
# Account analytics overview
curl "https://YOUR-DOMAIN/api/v1/analytics" \
-H "Authorization: Bearer YOUR_API_KEY"<?php
$key = 'YOUR_API_KEY';
$ctx = stream_context_create(['http' => [
'method' => 'POST',
'header' => "Authorization: Bearer $key\r\nContent-Type: application/json\r\n",
'content' => json_encode([
'url' => 'https://example.com/some/long/page',
'alias' => 'launch-2026',
'title' => 'Launch page',
]),
'ignore_errors' => true,
]]);
$res = file_get_contents('https://YOUR-DOMAIN/api/v1/links', false, $ctx);
$data = json_decode($res, true);
if ($data['ok']) {
echo $data['data']['short_url'], PHP_EOL; // https://YOUR-DOMAIN/launch-2026
} else {
echo 'Error: ', $data['error'], PHP_EOL;
}const res = await fetch('https://YOUR-DOMAIN/api/v1/links', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
url: 'https://example.com/some/long/page',
alias: 'launch-2026',
}),
});
const data = await res.json();
if (data.ok) {
console.log(data.data.short_url);
} else {
console.error(res.status, data.error);
}| Code | Meaning | Example |
|---|---|---|
200 | OK | Read / update / delete succeeded |
201 | Created | POST /api/v1/links succeeded |
400 | Bad request | Missing field, malformed URL, bad alias format |
401 | Unauthorized | Missing or invalid API key, disabled account |
403 | Forbidden | Plan lacks API access or the custom-alias feature |
404 | Not found | Link id does not exist (or belongs to another account) |
409 | Conflict | Alias already taken |
422 | Unprocessable | Monthly link quota reached, reserved alias, bad expiry |
429 | Too many requests | Per-key per-minute limit exceeded |
Full reference with every field documented lives in API.md at the project root.