Sink API

May 10, 2026 · View on GitHub

Sink provides a complete RESTful API for managing short links. Full API documentation is available via OpenAPI.

OpenAPI Documentation

  • OpenAPI JSON: /_docs/openapi.json
  • Scalar UI: /_docs/scalar
  • Swagger UI: /_docs/swagger

Visit your Sink instance at https://your-domain/_docs/scalar for interactive API documentation.

Authentication

All API endpoints require authentication via Bearer token in the Authorization header:

Authorization: Bearer YOUR_SITE_TOKEN

The token is the same as NUXT_SITE_TOKEN configured in your environment variables.

API Endpoints

MethodEndpointDescription
POST/api/link/createCreate a new short link
PUT/api/link/editUpdate an existing link
POST/api/link/upsertCreate or update a link by slug
POST/api/link/deleteDelete a link
GET/api/link/queryGet a link by slug
GET/api/link/searchSearch links
GET/api/link/listList all links (paginated)
GET/api/link/exportExport all links as paginated JSON
POST/api/link/importImport links from exported JSON
GET/api/link/aiGenerate an AI-powered slug suggestion
GET/api/link/og-aiGenerate AI-powered OpenGraph metadata
POST/api/upload/imageUpload an OpenGraph image to R2
POST/api/backupTrigger a manual KV backup to R2

Analytics

MethodEndpointDescription
GET/api/stats/countersGet analytics counters
GET/api/stats/metricsGet detailed metrics by dimension
GET/api/stats/viewsGet time-series view counts
GET/api/stats/heatmapGet heatmap data
GET/api/stats/exportExport access analytics as CSV
GET/api/logs/eventsGet real-time event logs
GET/api/logs/locationsGet recent access locations
POST /api/link/create
Authorization: Bearer SinkCool
Content-Type: application/json

{
  "url": "https://github.com/miantiao-me/Sink",
  "slug": "sink",
  "comment": "GitHub repo",
  "expiration": 1767225599,
  "apple": "https://apps.apple.com/app/id6745417598",
  "google": "https://play.google.com/store/apps/details?id=com.example",
  "geo": {
    "US": "https://example.com/us",
    "JP": "https://example.com/jp"
  },
  "title": "Sink - Link Shortener",
  "description": "A simple, speedy, secure link shortener",
  "image": "/_assets/images/sink/cover.webp",
  "password": "correct-horse-battery-staple",
  "unsafe": false,
  "redirectWithQuery": true
}

Response

{
  "link": {
    "id": "01jxyz...",
    "url": "https://github.com/miantiao-me/Sink",
    "slug": "sink",
    "comment": "GitHub repo",
    "createdAt": 1718119809,
    "updatedAt": 1718119809
  }
}

Request Body Fields

FieldTypeRequiredDescription
urlstringTarget URL (max 2048 chars)
slugstringCustom slug (auto-generated if omitted)
commentstringInternal note for the link
expirationnumberUnix timestamp in seconds; must be in the future
applestringApple device redirect URL
googlestringAndroid/Google Play redirect URL
geoobjectCountry-specific routing map, for example { "US": "https://..." }
titlestringOpenGraph title
descriptionstringOpenGraph description
imagestringOpenGraph image URL or uploaded asset path
cloakingbooleanEnable link cloaking (mask destination URL with short link)
redirectWithQuerybooleanAppend query parameters to destination URL (overrides global setting)
passwordstringPassword protection for the link (stored hashed)
unsafebooleanMark link as unsafe (shows warning page before redirect)

Routing Behavior

  • Geo-routing uses Cloudflare's request.cf.country value and two-letter ISO country codes. Keys are normalized to uppercase.
  • Device routing takes precedence over the default or geo-routed target when the visitor matches Apple or Android user agents.
  • If redirectWithQuery is enabled, query parameters from the short link are appended to the final target URL.

Password-protected links render an HTML password form for browser visitors. API or scripted clients can pass x-link-password when requesting the short link. Unsafe links require confirmation before redirecting; scripted clients can pass x-link-confirm: true after validating the destination.

Example: Generate OpenGraph Metadata with AI

GET /api/link/og-ai?url=https%3A%2F%2Fgithub.com%2Fmiantiao-me%2FSink&locale=en-US
Authorization: Bearer SinkCool
{
  "title": "Sink",
  "description": "A simple, speedy, secure link shortener with analytics on Cloudflare."
}

Example: Export Access Analytics as CSV

GET /api/stats/export?startAt=1717200000&endAt=1719791999&slug=sink
Authorization: Bearer SinkCool

The response is text/csv with these columns:

slug,url,viewer,views,referer
sink,https://github.com/miantiao-me/Sink,123,456,12

CORS

To enable CORS for API endpoints, set NUXT_API_CORS=true during build.