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