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"
}
FieldRequiredDescription
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

EndpointDescription
GET /api/listPaginated list (default 50)
GET /api/list/allAll mappings
GET /api/list/activeActive only
GET /api/list/inactiveInactive only
GET /api/list/expiredExpired only
GET /api/list/countCount 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

EndpointDescription
GET /api/list/import/staging/conflictsConflicting entries
GET /api/list/import/staging/invalidInvalid entries

Admin API — Statistics

EndpointDescription
GET /api/statistics/countTotal redirect count
GET /api/statistics/hourlyHourly breakdown
GET /api/statistics/dailyDaily breakdown
GET /api/statistics/timelineTimeline data
GET /api/statistics/configStatistics configuration
GET /api/statistics/debugRaw 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 — API Keys

EndpointDescription
GET /api/admin/apikeysList API keys for the current user
POST /api/admin/apikeysCreate a new API key (plaintext returned once)
DELETE /api/admin/apikeys/{id}Revoke an API key

Keys are persisted via EclipseStore and survive server restarts. Only the SHA-256 hash is stored — the plaintext is returned once at creation time.


MCP Server

The MCP server runs as a separate process on port 9091 (loopback by default). It exposes the shortener as Model Context Protocol tools over JSON-RPC 2.0.

POST /mcp
X-API-Key: <key>
Content-Type: application/json

Every request must carry a valid X-API-Key header, which is forwarded to the Admin API — jSentinel remains the single authorization point.

ToolDescription
create_short_linkCreate with optional alias, expiresAt, active
resolve_shortcodeLook up the original URL for a short code
edit_linkUpdate target URL or active state
toggle_activeToggle the active flag
delete_linkRemove a mapping
list_linksList with all | active | expired | inactive filter, query, limit
bulk_create_linksCreate multiple links in one call
bulk_validateValidate a batch without applying
export_linksExport all mappings as Base64-encoded ZIP
import_links_validateValidate a Base64 ZIP import
import_links_applyApply a previously validated import

Statistics tools

ToolDescription
get_statisticsTotal redirect count (all / single date / date range)
get_statistics_hourlyHourly breakdown per short code
get_statistics_dailyDaily breakdown per short code
get_statistics_timelineTimeline data
get_statistics_configRead statistics configuration
set_statistics_enabledEnable or disable statistics collection
update_statistics_configUpdate statistics configuration
export_statisticsExport statistics as Base64-encoded ZIP
import_statisticsImport statistics from Base64-encoded ZIP (idempotent)

Admin API — Preferences

EndpointDescription
GET /api/admin/preferences/columnsGet column visibility settings
POST /api/admin/preferences/columns/editBulk update preferences
POST /api/admin/preferences/columns/singleUpdate 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.

StatusCondition
302 FoundActive, non-expired mapping found
404 Not FoundUnknown short code
410 GoneMapping 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
}
CodeMeaning
400Invalid request body or URL
404Short code not found
409Alias already exists
422Alias policy violation
500Internal server error