How to use the shortener API
Everything the shortener interface does is a thin layer over a small REST API under /api/shortener/. Every response is JSON wrapped in success and data, every error comes back with a matching status code, and sending a key is optional — this guide covers the five calls that matter.
Authentication and limits
Sending a key is optional. Pass one as Authorization: Bearer aczh_... or X-API-Key: aczh_... and your request counts against that plan's monthly quota. Send nothing and it falls back to the anonymous limit of 40 creations per minute per IP address. Responses carry Access-Control-Allow-Origin: *, so a page you host yourself can call the API straight from the browser, and request bodies are JSON up to 1 MB.
Start without a key. Anonymous access covers scripts, prototypes and low-volume integrations. Reach for POST /api/shortener/keys with a name and a plan of free or pro only when you need a quota of your own — the raw key is returned once and never again.
What each endpoint does
| Call | What it does | Notes |
|---|---|---|
POST /api/shortener/shorten | Creates a link from a url, with optional customCode, mode, title and ISO expiresAt. Answers 201. | A customCode always wins over mode. |
GET /api/shortener/stats/:code | Returns the link record plus total clicks, clicks by day, top referrers and the latest 50 clicks. | Anyone who guesses the slug can read this. |
POST /api/shortener/keys | Mints an API key from a name and plan. Answers 201. | The raw key is shown once; only its hash is kept. |
GET /api/shortener/recent | Lists the 20 most recent active links with short URLs and QR addresses. | The Recent Links tab calls exactly this. |
GET /api/shortener/qr/:code | Redirects 302 to a 250 by 250 QR image for that short link. | An unknown code still returns a QR, pointing at the shortener itself. |
A complete example
Create a link with a readable slug, then read its stats back:
curl -X POST https://aczh.dev/api/shortener/shorten \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com/docs","customCode":"my-docs"}'
{"success":true,"data":{
"code":"my-docs",
"short_url":"https://aczh.dev/my-docs",
"qr_code_url":"https://aczh.dev/api/shortener/qr/my-docs",
"stats_url":"https://aczh.dev/shortener/#stats-my-docs"
}}
GET /api/shortener/stats/my-docs
The redirect itself is GET /<code>: a plain 302 to your destination with caching turned off so every visit is counted. An unknown code gets a small Link Not Found page and a 404; a code whose expiry has passed gets a 410 instead. The failures are explicit too: 400 for a missing or malformed URL, 401 for a bad key, and 429 when the rate limit or quota is used up.
Limits worth knowing
- The slug is the only key to a link. Because nobody signs in, anyone who guesses a code can read its click history — choose an unguessable custom slug for anything sensitive.
- Analytics are deliberately narrow. Total clicks, clicks per day, top ten referrers and the recent stream: no country, no device breakdown, no unique-visitor count, and the visitor address is stored only as an irreversible hash.
- Expiry is opt-in. Links never expire on their own; send an ISO
expiresAtwith the create call and the short URL answers410 Goneafter that moment. - Custom slugs are 3 to 30 characters. Letters, numbers, hyphens and underscores; a taken slug fails with a plain message and you pick another one.
Frequently asked questions
Do I need an API key to shorten a link?
No. Send nothing and the request falls back to the anonymous limit of 40 creations per minute per IP address.
Pass a key as Authorization Bearer or X-API-Key only when you want the request to count against that plan's monthly quota.
How do I create a short link with curl?
POST JSON with a url field to /api/shortener/shorten and read back code, short_url, qr_code_url and stats_url with a 201 status.
Add customCode for a readable slug, mode secure for a 12-character unguessable code, or mode sayable for a pronounceable one.
How do I read the clicks on a link I made?
GET /api/shortener/stats plus your code. The response carries the link record with its lifetime click count, clicks grouped by day capped at 30 rows, the top ten referrers, and the latest 50 clicks with timestamp, referrer and truncated user agent.
What do the API errors mean?
Every error comes back as JSON with an error field and a matching status code: 400 when url is missing or malformed, 401 for an unknown or deactivated key, 429 when the rate limit or the plan quota is used up, and a plain message when your custom slug is already taken.
Can I call the API from a browser page I host myself?
Yes. Responses carry Access-Control-Allow-Origin star, so your own page can call the endpoints straight from JavaScript.
Request bodies are JSON up to 1 MB, and every success response is wrapped in success and data.