API & MCP
KooLink exposes a small REST API plus an MCP server so users and AI agents can shorten links programmatically. All programmatic shortening is authenticated with an API key (a bearer token), not an OAuth session.
Get an API key
- Sign in → Dashboard → Settings → API Keys.
- Click Create key, optionally add a label (e.g. "My AI agent").
- Copy the key (
kl_…) — it is shown once.
Revoke anytime from the same card. A revoked key returns 401 on the API.
POST /api/v1/shorten
Create a short link attributed to the key's owner (so it earns).
Headers
Authorization: Bearer kl_<your-key>
Content-Type: application/json
Body
{ "url": "https://example.com/some/long/path", "label": "optional" }
Response (200)
{
"shortUrl": "https://kool.ink/abc123",
"code": "abc123",
"originalUrl": "https://example.com/some/long/path",
"id": "cl…",
"title": "Example Domain"
}
Errors
401— missing/invalid/revoked key.400— unsupported URL scheme or blocked destination.429— rate limited (per key).500— creation failed.
The endpoint reuses the same pipeline as the in-app shortener:
generateUniqueShortCode → parseDestinationUrl → basicSafetyCheck →
fetchDestinationTitle → Link.create.
Manage keys (session auth)
GET/POST/DELETE /api/account/api-keys — session-cookie authenticated, mirrors
the dashboard card. POST returns the raw token once; DELETE takes { id }.
MCP server
Two ways to let an agent shorten links:
- Hosted HTTP endpoint —
kool.ink/mcp(recommended). Point any MCP client at the URLhttps://kool.ink/mcp. No install, no local process. Supportsinitialize,tools/list, andtools/callover JSON-RPC (Streamable HTTP transport, connectionless). - Local stdio server — see
mcp/README.md. Zero-depnode server.mjsexposing the sameshorten_urltool; key viaKOOLINK_API_KEYenv var.
Both expose three tools:
| Tool | Args | Returns |
|---|---|---|
shorten_url | url (req), handle, label | short URL (https://kool.ink/CODE), code, original URL |
link_stats | code (req) | total vs valid views, by device / country / referrer, 7-day trend |
list_links | limit (opt, 1-100) | the owner's links with valid view counts |
Auth is optional
An API key is not required to use /mcp — an anonymous client can shorten
links straight away (links are created ownerless, like the landing shortener),
rate-limited per IP. Pass Authorization: Bearer *** (a key from Settings → API Keys) to **connect the session to your account**, which unlocks owner-scoped analytics: link_statsandlist_links` require a key and return a clear
"API key required" error without one.
Analytics endpoints
GET /api/v1/links — the key owner's links (most recent first) with valid view
counts. Optional ?limit=1..100 (default 20). Scoped to the key owner; never
returns other users' links.
GET /api/v1/links/[code]/stats — aggregated analytics for one owned link:
total vs valid (fraud-filtered) views, breakdowns by device / country /
referrer, and a trailing-7-day trend. Returns 404 for a code that is unknown
or belongs to another user (never reveals whether a code exists).
Both take Authorization: Bearer kl_…, support the same 401/429 errors as
/api/v1/shorten, and are exactly what link_stats / list_links call
under the hood.
Security notes
- Tokens are stored as a SHA-256 hash; the raw value lives only in the create response. A DB leak can't mint keys.
lastUsedAtis stamped on use (best-effort).- The
ApiKeytable is created by a migration that applies on deploy. It is additive (new table, cascade delete) and does not alter existing data.