Developer API
Use this guide to integrate 4lk.in from scripts, backends, or mobile apps. The API speaks JSON over HTTP; authenticated routes expect an Authorization header unless noted otherwise.
On this page
Quick start
- Base URL — all paths below are prefixed with this origin (no trailing slash):
https://api.4lk.in
- Authenticated requests — send
Authorization: Bearer <token>, where<token>is either a JWT access token or your API key string (see Authentication). - JSON bodies — use
Content-Type: application/json. - Short URLs in JSON — link objects include
shortUrl(absolute…/r/:slug). The API builds this from env, in order:PUBLIC_SHORT_ORIGIN,NEXT_PUBLIC_SHORT_ORIGIN,NEXT_PUBLIC_SITE_URL— align these with the host where redirects and QR scans resolve (often your apex/marketing site, not the API port). - Success responses — typically JSON with HTTP
200,201, or204(empty body on revoke API key).
Authentication
The API accepts one bearer credential per request. You can use either:
| Method | How you get it | Typical use |
|---|---|---|
| JWT access token | POST /auth/login or POST /auth/register — same flow as the web dashboard. | Browser apps you control, or server-side calls acting as the logged-in user. Does not consume API-key hourly quota on /links. |
| API key | Create one key per account under Dashboard → Developer API. Shown once in plaintext; we store a hash only. Rotate anytime — the previous key stops working immediately. | Servers, cron jobs, integrations. Counts toward hourly rate limits on /links (and related routes on that controller). |
Important: Managing keys (POST/GET/DELETE /apikeys) requires a JWT, not an API key — so automations should obtain a JWT once for provisioning, or keys are created manually in the dashboard.
API keys (JWT only)
| Method | Path | Purpose |
|---|---|---|
POST | /apikeys | Create or rotate key. Response includes plaintext apiKey once. |
GET | /apikeys | Status only: hasKey, createdAt — never returns the secret. |
DELETE | /apikeys | Revoke key. Response body empty — HTTP 204. |
Usage & limits
GET /developer/usage — JWT or API key. Returns JSON including hourly rate-limit usage (for API-key traffic), link quota, and whether an API key is active. Limits reset at the start of each UTC hour. Operators configure the hourly cap as developerApiRequestsPerHour in admin Configuration.
Links & analytics (JWT or API key)
These routes live under /links. Authenticate with either a JWT or an API key unless noted.
| Method | Path | Summary |
|---|---|---|
POST | /links | Create a short link (see body below). |
GET | /links | List recent links. Query: optional limit (1–100, default server-defined). |
GET | /links/browse | Paginated directory — page, pageSize, optional search, dateFrom, dateTo (YYYY-MM-DD). |
GET | /links/:id | :id is a UUID — fetch one link you own. |
PATCH | /links/:id | Partial update — include only fields to change. |
DELETE | /links/:id | Delete link. |
GET | /links/:id/analytics | Aggregate analytics for the link. |
GET | /links/:id/clicks | Paginated click log — supports filters via query params. |
GET | /links/:id/qr?format=png or svg | QR image download — binary response, attachment headers. |
Body for POST /links
| Field | Required | Rules |
|---|---|---|
destinationUrl | Yes | Full URL with protocol (e.g. https://…). |
slug | No | Optional custom short code when enabled in admin Configuration (Custom slug option). If omitted, empty, or the feature is off, the server assigns a random slug. Allowed characters: letters, digits, _, -; length 3–64. |
customSlug | No | Same meaning as slug, kept for older clients. If both are sent, slug wins. |
isDynamic, qrEnabled | No | Booleans; default false if omitted. |
Example response (201 Created): JSON includes id, slug, shortUrl (absolute …/r/:slugusing the API's configured public origin — same basis as QR codes), destinationUrl, timestamps, and totalClicks (often 0 for new rows). List/get/browse responses include shortUrl on each link as well.
Rate limiting & errors
429 Too Many Requests— hourly API-key quota exceeded on/linksroutes. Response may include aRetry-Afterheader (seconds until the next UTC hour boundary).401 Unauthorized— missing or invalid bearer token / API key.409 Conflict— slug already taken (create/update).400 Bad Request— validation errors. Extra properties in JSON bodies are rejected — only use fields documented here. Destination URLs must usehttporhttps, must not point at localhost or private networks, and may be rejected if they match the platform blocklist (admin-configured domains).
Copy-paste examples
Replace YOUR_API_KEY with your secret (starts with 4lk.). On Windows PowerShell, JSON quoting can be awkward — write the body to a UTF-8 file and use curl.exe --data-binary @path.
Create link — random slug
curl -sS -w "\nHTTP %{http_code}\n" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"destinationUrl":"https://example.com/page"}' \
"https://api.4lk.in/links"Create link — custom slug (optional)
curl -sS \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"destinationUrl":"https://example.com/page","slug":"my-campaign"}' \
"https://api.4lk.in/links"Create link — empty slug means auto
curl -sS \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"destinationUrl":"https://example.com/page","slug":""}' \
"https://api.4lk.in/links"Check usage
curl -sS \ -H "Authorization: Bearer YOUR_API_KEY" \ "https://api.4lk.in/developer/usage"