API Documentation

Manage your short links and retrieve click statistics programmatically. The API speaks JSON and lives under http://adr.pm/api/v1. Send Accept: application/json with every request.

Authentication

All endpoints require a personal access token. Create one under your profile — the token is shown once, right after creation. Send it as a bearer token:

Authorization: Bearer <your-token>

Requests without a valid token receive 401 Unauthorized. A token has the same access as the user who created it: addresses in your own groups.

Endpoints

Method Endpoint Description
GET /api/v1/addresses Paginated list of your addresses, newest first, with click counts.
POST /api/v1/addresses Create a short link. Body: group_id, destination. Returns 201 Created.
GET /api/v1/addresses/{id} Show a single address with its click count.
PUT /api/v1/addresses/{id} Update the destination. The short code never changes.
DELETE /api/v1/addresses/{id} Delete an address. Returns 204 No Content.
GET /api/v1/stats Click statistics across your groups. Optional ?group_id= filter.

Accessing an address outside your groups returns 403; creating in a group you are not a member of returns 404.

Example: create a short link

curl -X POST http://adr.pm/api/v1/addresses \
  -H "Authorization: Bearer <your-token>" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{"group_id": 1, "destination": "https://example.com/very/long/url"}'

Response 201 Created:

{
  "data": {
    "id": 1,
    "group_id": 1,
    "destination": "https://example.com/very/long/url",
    "identifyer": "xyz12",
    "short_url": "http://adr.pm/xyz12",
    "created_at": "2026-07-10T16:25:13.000000Z",
    "updated_at": "2026-07-10T16:25:13.000000Z"
  }
}

Example: statistics

curl http://adr.pm/api/v1/stats \
  -H "Authorization: Bearer <your-token>" \
  -H "Accept: application/json"

Response 200 OK:

{
  "data": {
    "active_links": 12,
    "total_clicks": 340,
    "clicks_this_week": 25,
    "avg_clicks_per_link": 28,
    "click_trends": {
      "labels": ["Jun 11", "Jun 12", "Jun 13"],
      "counts": [3, 7, 0]
    },
    "top_links": [
      {
        "id": 1,
        "group_id": 1,
        "destination": "https://example.com/very/long/url",
        "identifyer": "xyz12",
        "short_url": "http://adr.pm/xyz12",
        "clicks_count": 120,
        "created_at": "2026-07-10T16:25:13.000000Z",
        "updated_at": "2026-07-10T16:25:13.000000Z"
      }
    ]
  }
}

click_trends covers the last 30 days, one entry per day.

Errors and pagination

Invalid input returns 422 Unprocessable Content with a message and per-field errors:

{
  "message": "The destination field must be a valid URL.",
  "errors": {
    "destination": ["The destination field must be a valid URL."]
  }
}

The address list is paginated. Use ?page= to navigate; each response includes links and meta objects with the current page, last page and totals.

Ready to try it out?

Create Account