docs
API Reference
Complete REST API documentation for the URL Shortener admin and redirect endpoints.
The Admin API runs on port 9090 (localhost only by default). The redirect endpoint runs on port 8081 (public).
Admin API — URL Mappings
Create Short URL
POST /api/shorten
Request body:
{
"originalUrl": "https://example.com/very/long/path",
"alias": "my-link",
"expiresAt": "2025-12-31T23:59:59Z"
}
| Field | Required | Description |
|---|---|---|
originalUrl |
✅ | The target URL |
alias |
❌ | Custom short code (3–32 chars, [A-Za-z0-9_-]) |
expiresAt |
❌ | ISO 8601 expiry timestamp |
Response 201 Created:
{
"shortCode": "my-link",
"originalUrl": "https://example.com/very/long/path",
"active": true,
"createdAt": "2025-01-01T10:00:00Z",
"expiresAt": "2025-12-31T23:59:59Z"
}
List Mappings
| Endpoint | Description |
|---|---|
GET /api/list |
Paginated list (default 50) |
GET /api/list/all |
All mappings |
GET /api/list/active |
Active only |
GET /api/list/inactive |
Inactive only |
GET /api/list/expired |
Expired only |
GET /api/list/count |
Count statistics |
Response 200 OK:
[
{
"shortCode": "my-link",
"originalUrl": "https://example.com/very/long/path",
"active": true,
"createdAt": "2025-01-01T10:00:00Z"
}
]
Edit Mapping
POST /api/edit
{
"shortCode": "my-link",
"originalUrl": "https://new-target.com",
"active": true
}
Delete Mapping
POST /api/delete
{ "shortCode": "my-link" }
Toggle Active
POST /api/toggleActive
{ "shortCode": "my-link" }
Admin API — Import / Export
Export
GET /api/list/export
Downloads a ZIP archive containing all mappings as JSON.
Validate Import
POST /api/list/import/validate
Content-Type: multipart/form-data
Returns validation results before applying. Detects conflicts and invalid entries.
Apply Import
POST /api/list/import/apply
Applies a previously validated import staging.
Check Staging
| Endpoint | Description |
|---|---|
GET /api/list/import/staging/conflicts |
Conflicting entries |
GET /api/list/import/staging/invalid |
Invalid entries |
Admin API — Statistics
| Endpoint | Description |
|---|---|
GET /api/statistics/count |
Total redirect count |
GET /api/statistics/hourly |
Hourly breakdown |
GET /api/statistics/daily |
Daily breakdown |
GET /api/statistics/timeline |
Timeline data |
GET /api/statistics/config |
Statistics configuration |
GET /api/statistics/debug |
Raw event data (debug) |
Hourly response example:
{
"shortCode": "my-link",
"buckets": [
{ "hour": "2025-01-01T10:00:00Z", "count": 42 },
{ "hour": "2025-01-01T11:00:00Z", "count": 17 }
]
}
Admin API — Preferences
| Endpoint | Description |
|---|---|
GET /api/admin/preferences/columns |
Get column visibility settings |
POST /api/admin/preferences/columns/edit |
Bulk update preferences |
POST /api/admin/preferences/columns/single |
Update single preference |
Admin API — Store Info
GET /api/store/info
Returns metadata about the active storage backend (type, record count, last modified).
Redirect Endpoint
GET /{shortCode}
Ports: 8081 — public-facing, no authentication.
| Status | Condition |
|---|---|
302 Found |
Active, non-expired mapping found |
404 Not Found |
Unknown short code |
410 Gone |
Mapping exists but is inactive or expired |
Records a RedirectEvent (timestamp, User-Agent, Referer, IP hash, Accept-Language) on every successful redirect.
Error Responses
All error responses use a consistent JSON envelope:
{
"error": "ALIAS_ALREADY_EXISTS",
"message": "The alias 'my-link' is already in use.",
"status": 409
}
| Code | Meaning |
|---|---|
400 |
Invalid request body or URL |
404 |
Short code not found |
409 |
Alias already exists |
422 |
Alias policy violation |
500 |
Internal server error |