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 — API Keys
| Endpoint | Description |
|---|---|
GET /api/admin/apikeys | List API keys for the current user |
POST /api/admin/apikeys | Create 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.
Link tools
| Tool | Description |
|---|---|
create_short_link | Create with optional alias, expiresAt, active |
resolve_shortcode | Look up the original URL for a short code |
edit_link | Update target URL or active state |
toggle_active | Toggle the active flag |
delete_link | Remove a mapping |
list_links | List with all | active | expired | inactive filter, query, limit |
bulk_create_links | Create multiple links in one call |
bulk_validate | Validate a batch without applying |
export_links | Export all mappings as Base64-encoded ZIP |
import_links_validate | Validate a Base64 ZIP import |
import_links_apply | Apply a previously validated import |
Statistics tools
| Tool | Description |
|---|---|
get_statistics | Total redirect count (all / single date / date range) |
get_statistics_hourly | Hourly breakdown per short code |
get_statistics_daily | Daily breakdown per short code |
get_statistics_timeline | Timeline data |
get_statistics_config | Read statistics configuration |
set_statistics_enabled | Enable or disable statistics collection |
update_statistics_config | Update statistics configuration |
export_statistics | Export statistics as Base64-encoded ZIP |
import_statistics | Import statistics from Base64-encoded ZIP (idempotent) |
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 |
