API
A JSON API. Reading is open; creating needs a key.
Base
Every endpoint lives on api.kortste.link. The redirect is the exception: it lives on the short domain, because that is the whole point of it.
Getting a key
Creating a link needs a key. Looking one up, following a redirect and reporting abuse do not.
There is no signup form and no dashboard, because there are no accounts — not for this API and not for the service. Mail keys@kortste.link with a line about what you are building and you get one back, issued by hand.
A new key allows 5 creates a minute and 50 a day. Small on purpose: this API is goodwill rather than a product, and someone pays for it out of pocket. Ask through the support link at the foot of this page and the allowance goes up.
Send it as a header, never in a query string. Query strings end up in server logs, browser history and referrer headers, which is a poor place to leave a credential — doubly so on a link shortener.
Authorization: Bearer kl_live_...
The key is shown once, at issuance, and only its hash is stored. Nobody can send it to you a second time, so a lost key is revoked and replaced rather than recovered. Mail the same address to have one revoked: it stops working on the next request.
Endpoints
POST
/v1/links
Create a short link
key
curl -X POST https://api.kortste.link/v1/links \
-H 'Authorization: Bearer kl_live_...' \
-H 'Content-Type: application/json' \
-d '{"url":"https://seznam.cz/m/sem/1345"}'
{
"code": "fp9qm3",
"shortUrl": "https://kortste.link/fp9qm3",
"url": "https://seznam.cz/m/sem/1345",
"createdAt": "2026-08-22T18:49:11.665Z"
}
- 201
- Created. The body carries code, shortUrl, url and createdAt.
- 400
- The body is not valid JSON.
- 401
- No key, or one that is unknown or revoked.
- 422
- The URL was rejected. The detail field says why.
- 429
- Over this key's allowance. Retry-After says how long to wait.
GET
/v1/links/{code}
Look a link up without opening it
Reveals where a code points without visiting it, which is a safety feature rather than an oversight: it needs no key for the same reason.
curl https://api.kortste.link/v1/links/fp9qm3
- 200
- The same fields as creation.
- 404
- No such code.
- 410
- The link was taken down.
GET
/{code}
The redirect itself
curl -i https://kortste.link/fp9qm3
Deliberately 302 and not 301: a permanent redirect is remembered by browsers more or less forever, which would make a link impossible to take back.
- 302
- The Location header carries the destination.
- 404
- No such code.
- 410
- The link was taken down.
POST
/v1/abuse
Report a link for abuse
No key, on purpose. Someone reporting a phishing link is exactly the person least likely to hold one, and a credential between us and that report would be a worse trade than any abuse it prevented.
curl -X POST https://api.kortste.link/v1/abuse \
-H 'Content-Type: application/json' \
-d '{"code":"fp9qm3","reason":"phishing"}'
- 202
- Recorded. A person reads it; a report alone revokes nothing.
- 422
- Unknown code, or no reason given.
GET
/healthz
Status check
curl https://api.kortste.link/healthz
- 200
- The body is the word ok.
Errors
Errors follow RFC 9457 and come back as application/problem+json with type, title, status and detail. One shape for every failure, so a client writes one handler.
A missing key, a malformed one, an unknown one and a revoked one all answer the same 401. That is deliberate: any difference between them would turn this endpoint into an oracle for probing which keys exist.
Limits
Creating through the API is limited per key, so two callers never share an allowance and no key earns a fresh one by changing address. The form on the front page holds no key and is limited per address instead. Redirects are never limited: throttling them would throttle the product.