Kin Shortener API Docs v1.0.0 Open app
API Reference

Kin Shortener API

A minimal, public HTTP API for creating and resolving short links. One endpoint to shorten, one redirect to resolve — served from Cloudflare’s edge with no keys to manage.

v1.0.0 REST JSON Public
Base URL https://kinshortner-api.gamedevinc6.workers.dev
Short domain https://kinshortner.pages.dev

Request bodies and success responses are JSON encoded in UTF-8. Every API response includes permissive CORS headers, so browser-based clients can call the API directly.

Build your own shortener

Copy the complete documentation as Markdown — API contract, Worker source, routing rules, and deployment steps — then hand it to an AI assistant to rebuild this stack.

Quick start #

Create your first short link in three steps. No installation or authentication is required.

  1. Send the destination URL. Make a POST request to /api/shorten with a JSON body containing the url field.
  2. Read the short link. A successful request returns 200 OK and a JSON object with a shortUrl field.
  3. Share it. Requests to the short link respond with 302 Found and a Location header pointing at the destination.
curl -X POST "https://kinshortner-api.gamedevinc6.workers.dev/api/shorten" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://example.com/handbook/chapter-1"}'

Authentication #

The Kin Shortener API is public. It does not require an API key, OAuth token, or account, and there is nothing to configure before your first request.

No credentials

Authorization headers are ignored. Do not send secrets to the API, and avoid shortening URLs that contain personal or confidential information, since short links are publicly resolvable.

Conventions #

  • All traffic uses HTTPS; every route is available on the base URL shown above.
  • Request and response bodies are UTF-8 JSON, except 404 responses, which are plain text.
  • Send Content-Type: application/json with every POST request.
  • Unknown fields in a request body are ignored; only url is read.
  • Short codes are six characters from a–z and 0–9, generated once per request, and are case-sensitive.
  • Each successful POST creates a new code, even when the same URL was shortened before.

Errors #

APIs fail in predictable ways. The table below lists every response the API returns for invalid requests or missing links.

Status Content type Body Cause
400 application/json {"error":"Missing URL"} Valid JSON was sent, but url was absent or empty.
400 application/json {"error":"Invalid JSON payload"} The request body could not be parsed as JSON.
404 text/plain Kin Shortener - Link not found or expired, Links expire after 24 hours... No link exists for the requested code, or its 24-hour lifetime has elapsed.
5xx text/plain edge error page An unexpected failure occurred at the edge. Retry with backoff.

Error payloads

Missing URL · 400
{
  "error": "Missing URL"
}
Invalid JSON · 400
{
  "error": "Invalid JSON payload"
}
Parse by content type

Check response.ok before reading a body. On 400 the body is JSON; on 404 it is plain text. Branch on the Content-Type header instead of guessing the shape.

CORS #

The API is callable from browsers without a proxy. Responses from /api/shorten — including 400 errors — and preflight responses include the following headers.

Header Value
Access-Control-Allow-Origin *
Access-Control-Allow-Headers Content-Type
Access-Control-Allow-Methods GET, POST, OPTIONS

Preflight (OPTIONS) requests return 200 OK with an empty body. Credentialed requests are not supported: the API never issues or reads cookies, so send credentials: "omit" (the fetch default) and no Authorization header.

Redirect and 404 responses are served without CORS headers because they are meant for top-level navigation. A browser fetch to a missing or expired code therefore rejects as a network error; server-side clients still receive the plain-text body.

Limits #

  • No API keys, accounts, or per-user quotas exist in v1.
  • The API does not currently expose analytics, listing, or deletion endpoints.
  • If a request fails with a 5xx status, retry with exponential backoff rather than immediately resending.
  • Short links should be treated as public: anyone with a code can resolve it.
  • Links expire 24 hours after creation. There is no renewal or extension endpoint.

Reference implementation #

Kin Shortener runs as a single Cloudflare Worker backed by Workers KV. The routing core from the v1 Worker is reproduced below — small enough to audit in one pass, and reusable if you want to self-host the same API contract. The deployed Worker adds a 24-hour link lifetime and the longer not-found message documented above.

Component Implementation
Runtime Cloudflare Workers, ES module syntax
Storage Workers KV namespace bound as URL_MAP
Short domain Set by the shortDomain constant inside the Worker
Routing OPTIONS preflight · POST /api/shorten · GET /{code}
Operational notes

Workers KV is eventually consistent, so a newly created link can take up to about a minute to resolve in every region. Codes are generated with Math.random().toString(36), which is not meant to be unguessable — never treat a code as an access token. In production, each entry is written with a 24-hour expiration, so links stop resolving after that window.

Worker source

worker.js
export default {
  async fetch(request, env) {
    const url = new URL(request.url);

    const corsHeaders = {
      "Access-Control-Allow-Origin": "*",
      "Access-Control-Allow-Methods": "GET, POST, OPTIONS",
      "Access-Control-Allow-Headers": "Content-Type",
    };

    if (request.method === "OPTIONS") {
      return new Response(null, { headers: corsHeaders });
    }

    // 1. POST /api/shorten endpoint
    if (request.method === "POST" && url.pathname === "/api/shorten") {
      try {
        const body = await request.json();
        if (!body.url) {
          return new Response(JSON.stringify({ error: "Missing URL" }), {
            status: 400,
            headers: { ...corsHeaders, "Content-Type": "application/json" }
          });
        }

        const code = Math.random().toString(36).substring(2, 8);
        await env.URL_MAP.put(code, body.url);

        // HERE: Set your short URL domain to your Cloudflare Pages domain
        const shortDomain = "https://kinshortner.pages.dev";

        return new Response(JSON.stringify({ shortUrl: `${shortDomain}/${code}` }), {
          headers: { ...corsHeaders, "Content-Type": "application/json" }
        });
      } catch (err) {
        return new Response(JSON.stringify({ error: "Invalid JSON payload" }), {
          status: 400,
          headers: { ...corsHeaders, "Content-Type": "application/json" }
        });
      }
    }

    // 2. GET /:code endpoint (Redirects to original link)
    const code = url.pathname.slice(1);
    if (code) {
      const longUrl = await env.URL_MAP.get(code);
      if (longUrl) {
        return Response.redirect(longUrl, 302);
      }
    }

    return new Response("Kin Shortener - Link not found", { status: 404 });
  }
};
Self-hosting

To deploy your own instance, change shortDomain to your Pages domain, bind a KV namespace named URL_MAP in your Wrangler configuration, and redeploy. No client changes are required as long as the routes and response shapes stay the same.

Changelog #

v1.0.0 October 31, 2026 — Initial public release.
POST /api/shorten creates links · GET /{code} redirects · CORS enabled for browser clients.
Update October 31, 2026 — 24-hour link lifetime.
Links expire one day after creation and return the updated not-found message when resolved afterwards.