The REST API
The base URL is https://api.frwrd.to. Every call except creating and recovering a workspace takes your workspace key as a bearer token:
Authorization: Bearer fw_...
The examples below read the key from $FRWRD_KEY. Bodies are JSON unless the example says otherwise.
Links
Create a short link:
curl -X POST https://api.frwrd.to/v1/links -H "Authorization: Bearer $FRWRD_KEY" -H "Content-Type: application/json" -d '{"long_url":"https://example.com/a/long/address","title":"Example"}'
The answer has the short link, its hash and the addresses of its QR code. Only http and https targets are accepted. You can also send tags, utm and, on a verified workspace, your own hash.
List links, newest first (limit up to 200, and offset):
curl "https://api.frwrd.to/v1/links?limit=50" -H "Authorization: Bearer $FRWRD_KEY"
Numbers for one link, by default the last 30 days (since and until take a date such as 2026-10-01, at most 366 days apart):
curl "https://api.frwrd.to/v1/links/aB3xZ9/stats?since=2026-10-01" -H "Authorization: Bearer $FRWRD_KEY"
The answer gives the total, the split by channel (link for a direct click, qr for a scan, page for a click on a bio page) and the numbers per day.
The QR code, as PNG or SVG (size from 128 to 2048):
curl "https://api.frwrd.to/v1/links/aB3xZ9/qr.png?size=512" -H "Authorization: Bearer $FRWRD_KEY" -o code.png
To change a link, send PATCH /v1/links/{hash} with any of long_url, title, tags and archived. DELETE /v1/links/{hash} archives it: it stops redirecting, and its numbers stay.
Pages
A page is a Markdown document with a short header. You save the whole document in one call. The path - is the root page; a page in another language lives under its language code, and the slash is written %2F, as in de%2Fhilfe.
curl -X PUT https://api.frwrd.to/v1/pages/hello -H "Authorization: Bearer $FRWRD_KEY" -H "Content-Type: text/markdown" --data-binary @hello.md
Every link in the document becomes a short link of your workspace. To read a page back as Markdown, send Accept: text/markdown; the answer carries an ETag. Send it back as If-Match when you save, and the call fails with 412 if someone changed the page meanwhile.
Views of a page and clicks on each of its links:
curl "https://api.frwrd.to/v1/pages/hello/stats" -H "Authorization: Bearer $FRWRD_KEY"
GET /v1/pages lists your pages, GET /v1/pages/{path}/versions shows the history and DELETE /v1/pages/{path} archives a page.
Bit.ly compatible /v4
Tools that speak Bit.ly's v4 API can point at https://api.frwrd.to/v4 and use your workspace key as the token. These calls exist, with Bit.ly's answers, timestamps and error messages:
- POST /v4/shorten
- POST /v4/expand
- PATCH /v4/bitlinks/frwrd.to/{hash}
- GET /v4/bitlinks/frwrd.to/{hash}/clicks/summary
Anything else of Bit.ly's is not served. A spent link quota answers 429 with MONTHLY_LIMIT_EXCEEDED.
Limits and errors
- Before it checks your key, the API allows 20 requests per second from one address (bursts of 60). After that, 10 per second for each workspace (bursts of 30). Creating or recovering workspaces is limited to 5 per minute per address.
- Over a limit, the answer is 429 with the code rate_limited, and a Retry-After header says when to try again.
- Errors on /v1 are JSON: {"error":{"code":"...","message":"..."}}. Branch on code: invalid_body, missing_credentials, invalid_credentials, not_found, conflict, precondition_failed, quota_exceeded, not_verified, rate_limited or internal_error.
The full contract is an OpenAPI document that lives with the source code, which is not public yet. Until then, the calls above, the MCP tool descriptions and frwrd.to/llms.txt describe the API.