Skip to main content
The URL management endpoints allow both authenticated and anonymous users to create and manage shortened URLs. Authenticated users can create permanent links, while anonymous users create temporary links with an 8-hour expiration.

Create Short URL (Authenticated)

Create a permanent shortened URL associated with your account.
curl -X POST http://localhost:8080/api/urls \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -d '{
    "originalUrl": "https://example.com/very-long-url"
  }'

Endpoint

POST /api/urls

Headers

Authorization
string
required
Bearer token obtained from /api/auth/login or /api/auth/register.Format: Bearer <token>

Request Body

originalUrl
string
required
The long URL to shorten. Must start with http://, https://, or ftp://. Maximum 2048 characters.

Response

id
integer
Unique identifier for this short URL.
originalUrl
string
The original long URL.
shortCode
string
The generated 7-character alphanumeric code (e.g., aB3xYz7).
shortUrl
string
Fully-qualified short URL ready to share (e.g., https://short.ly/aB3xYz7).
createdAt
string
ISO 8601 timestamp of creation.
expiresAt
string | null
Expiration timestamp. null for permanent (authenticated) links.
Either TEMPORARY or PERMANENT.
status
string
Current status: ACTIVE, EXPIRED, or DELETED.
redirectCount
integer
Total number of times this link has been followed.
avgRedirectMs
number | null
Running average redirect latency in milliseconds. null until first redirect.
destinationStatus
integer | null
Last HTTP status code of the destination URL. null until first availability check.
lastCheckedAt
string | null
When the destination was last checked for availability.

Status Codes

201 Created
Success
Short URL successfully created.
400 Bad Request
Error
Invalid URL format or validation error.
401 Unauthorized
Error
Missing or invalid JWT token.

Example Response

{
  "id": 42,
  "originalUrl": "https://example.com/very-long-url",
  "shortCode": "aB3xYz7",
  "shortUrl": "https://short.ly/aB3xYz7",
  "createdAt": "2024-03-15T10:30:00Z",
  "expiresAt": null,
  "linkType": "PERMANENT",
  "status": "ACTIVE",
  "redirectCount": 0,
  "avgRedirectMs": null,
  "destinationStatus": null,
  "lastCheckedAt": null
}

Create Short URL (Anonymous)

Create a temporary shortened URL without authentication. The link expires after 8 hours.
curl -X POST http://localhost:8080/api/urls/public \
  -H "Content-Type: application/json" \
  -d '{
    "originalUrl": "https://example.com/temporary-link"
  }'

Endpoint

POST /api/urls/public

Request Body

originalUrl
string
required
The long URL to shorten. Must start with http://, https://, or ftp://. Maximum 2048 characters.

Response

Same as authenticated endpoint, but expiresAt will be set to 8 hours from creation, and linkType will be TEMPORARY.

Status Codes

201 Created
Success
Short URL successfully created.
400 Bad Request
Error
Invalid URL format or validation error.

Example Response

{
  "id": 43,
  "originalUrl": "https://example.com/temporary-link",
  "shortCode": "xY9pQw2",
  "shortUrl": "https://short.ly/xY9pQw2",
  "createdAt": "2024-03-15T10:30:00Z",
  "expiresAt": "2024-03-15T18:30:00Z",
  "linkType": "TEMPORARY",
  "status": "ACTIVE",
  "redirectCount": 0,
  "avgRedirectMs": null,
  "destinationStatus": null,
  "lastCheckedAt": null
}

List My URLs

Retrieve all shortened URLs owned by the authenticated user, sorted by newest first.
curl -X GET http://localhost:8080/api/urls \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"

Endpoint

GET /api/urls

Headers

Authorization
string
required
Bearer token obtained from /api/auth/login or /api/auth/register.

Response

Array of short URL objects (same structure as create response).

Status Codes

200 OK
Success
Returns list of user’s URLs.
401 Unauthorized
Error
Missing or invalid JWT token.

Example Response

[
  {
    "id": 42,
    "originalUrl": "https://example.com/page1",
    "shortCode": "aB3xYz7",
    "shortUrl": "https://short.ly/aB3xYz7",
    "createdAt": "2024-03-15T10:30:00Z",
    "expiresAt": null,
    "linkType": "PERMANENT",
    "status": "ACTIVE",
    "redirectCount": 125,
    "avgRedirectMs": 42.3,
    "destinationStatus": 200,
    "lastCheckedAt": "2024-03-15T12:00:00Z"
  },
  {
    "id": 41,
    "originalUrl": "https://example.com/page2",
    "shortCode": "xY9pQw2",
    "shortUrl": "https://short.ly/xY9pQw2",
    "createdAt": "2024-03-15T09:15:00Z",
    "expiresAt": null,
    "linkType": "PERMANENT",
    "status": "ACTIVE",
    "redirectCount": 87,
    "avgRedirectMs": 38.7,
    "destinationStatus": 200,
    "lastCheckedAt": "2024-03-15T11:45:00Z"
  }
]

Delete Short URL

Soft-delete a shortened URL. The link will be marked as DELETED and will no longer redirect.
curl -X DELETE http://localhost:8080/api/urls/42 \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"

Endpoint

DELETE /api/urls/{id}

Path Parameters

id
integer
required
The unique identifier of the short URL to delete.

Headers

Authorization
string
required
Bearer token obtained from /api/auth/login or /api/auth/register.

Response

No response body.

Status Codes

204 No Content
Success
Short URL successfully deleted.
401 Unauthorized
Error
Missing or invalid JWT token, or attempting to delete another user’s URL.
404 Not Found
Error
Short URL with the specified ID not found.

Sync Anonymous URLs

Bulk-sync anonymous URLs from localStorage to the authenticated user’s account. This endpoint is called after registration or login to convert temporary links to permanent ones.
curl -X POST http://localhost:8080/api/urls/sync \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -d '{
    "urls": [
      "https://example.com/page1",
      "https://example.com/page2",
      "https://example.com/page3"
    ]
  }'

Endpoint

POST /api/urls/sync

Headers

Authorization
string
required
Bearer token obtained from /api/auth/login or /api/auth/register.

Request Body

urls
array
required
List of original URLs to sync. Maximum 100 URLs per request. Duplicates (URLs already owned by the user) are silently skipped.

Response

Returns the user’s complete updated URL list after syncing (same structure as GET /api/urls).

Status Codes

200 OK
Success
URLs successfully synced. Returns updated list of all user URLs.
400 Bad Request
Error
Invalid request (empty array, more than 100 URLs).
401 Unauthorized
Error
Missing or invalid JWT token.

Example Response

[
  {
    "id": 42,
    "originalUrl": "https://example.com/page1",
    "shortCode": "aB3xYz7",
    "shortUrl": "https://short.ly/aB3xYz7",
    "createdAt": "2024-03-15T10:30:00Z",
    "expiresAt": null,
    "linkType": "PERMANENT",
    "status": "ACTIVE",
    "redirectCount": 5,
    "avgRedirectMs": 45.2,
    "destinationStatus": null,
    "lastCheckedAt": null
  }
]

Business Rules

Anonymous vs Authenticated Links
  • Anonymous links (POST /api/urls/public):
    • Expire after 8 hours
    • linkType: TEMPORARY
    • Stored in browser localStorage
    • Automatically synced upon login/registration
  • Authenticated links (POST /api/urls):
    • Never expire (expiresAt: null)
    • linkType: PERMANENT
    • Associated with user account
    • Can be listed and deleted
URL ValidationAll URLs must:
  • Start with http://, https://, or ftp://
  • Be at most 2048 characters long
  • Be properly formatted according to RFC 3986

Build docs developers (and LLMs) love