shortcode
Log in Sign upSign up
Developers

API docs

Create and manage short links programmatically: bring short-code.io into your own products, scripts, and workflows.

Getting started

The short-code.io API lets you create, list, update, and delete short links without touching the dashboard, useful for provisioning links from your own app, CI pipeline, or CMS.

API access is available on the Pro plan and above. To create a key, open the dashboard, click your avatar in the top right, and choose API keys. You can have up to 10 keys per account at a time.

The full key is shown once, right after creation. Copy it somewhere safe. Only a short prefix is kept visible afterwards so you can tell your keys apart. You can revoke any key at any time; requests using a revoked key are rejected immediately.

Authentication

Send your key as a bearer token on every request:

Authorization: Bearer sc_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Keys are secrets. Never embed an API key in client-side or browser code, mobile app bundles, or public repositories: anyone with the key can manage links on your account. Call the API only from your own backend.

Base URL

All endpoints below are relative to:

https://api.short-code.io

Endpoints

GET/v1/links

List every short link on your account, including the same click analytics the dashboard shows: totals for today, the last 7 days, and the last 30 days, a per-day series covering the last 30 days (by_day, days without clicks omitted), and the percentage share per country of origin (by_origin, ISO 3166-1 alpha-2 codes).

Request
$ curl https://api.short-code.io/v1/links \
    -H 'Authorization: Bearer sc_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
Response · 200 OK
{
  "links": [
    {
      "uuid": "9c3f1e2a-4b7d-4a10-9e2f-6d8c1a5b7e90",
      "domain": "srtco.de",
      "title": "Launch page",
      "code": "x9K2mQ7z",
      "named": false,
      "short_url": "https://srtco.de/x9K2mQ7z",
      "destination": "https://acme.com/launch",
      "clicks": {
        "count": { "total": 128, "day": 3, "week": 24, "month": 97 },
        "by_day": [
          { "date": "2026-07-17", "clicks": 21 },
          { "date": "2026-07-18", "clicks": 3 }
        ],
        "by_origin": { "DE": 67, "US": 33 }
      },
      "created": "2026-06-02T09:14:22.000Z",
      "updated": "2026-07-18T15:02:11.000Z"
    }
  ]
}
POST/v1/links

Create a new short link. destination is required and must be a valid http(s) URL. domain is optional and defaults to the shared short domain (srtco.de); to use a custom domain, add it in the dashboard first. code is optional: supply it to create a named link with a code you choose, or omit it for a generated one. title is optional too: a label of up to 120 characters, private to your account, returned as null when you send none. Visitors never see it.

On the shared domain, a code is 5–32 characters; on your own domain, it is 1–32 characters. Codes may contain a-z, A-Z, 0-9, - and _, with no leading, trailing or repeated separator. The case you send is preserved, but codes are compared case-insensitively, so /Menu and /menu are the same link. Some codes are reserved. On the shared domain, codes containing inappropriate language or common obfuscations are also rejected. A code is permanent: it can't be changed later, so a printed QR keeps working. A code you choose on the shared domain is a named link: it counts against your plan's allowance and stops resolving if your subscription lapses. On your own domain codes are yours to hand out: unlimited, outside that allowance, and returned with "named": false.

Request · default domain
$ curl -X POST https://api.short-code.io/v1/links \
    -H 'Authorization: Bearer sc_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' \
    -H 'Content-Type: application/json' \
    -d '{ "destination": "https://acme.com/launch" }'
Request · custom domain
$ curl -X POST https://api.short-code.io/v1/links \
    -H 'Authorization: Bearer sc_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' \
    -H 'Content-Type: application/json' \
    -d '{ "domain": "go.acme.com", "destination": "https://acme.com/launch" }'
Request · named link
$ curl -X POST https://api.short-code.io/v1/links \
    -H 'Authorization: Bearer sc_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' \
    -H 'Content-Type: application/json' \
    -d '{ "code": "summer-sale", "destination": "https://acme.com/launch", "title": "Summer sale" }'
Response · 201 Created
{
  "uuid": "9c3f1e2a-4b7d-4a10-9e2f-6d8c1a5b7e90",
  "domain": "srtco.de",
  "title": "Summer sale",
  "code": "summer-sale",
  "named": true,
  "short_url": "https://srtco.de/summer-sale",
  "destination": "https://acme.com/launch",
  "clicks": {
    "count": { "total": 0, "day": 0, "week": 0, "month": 0 },
    "by_day": [],
    "by_origin": {}
  },
  "created": "2026-07-23T10:41:03.000Z",
  "updated": "2026-07-23T10:41:03.000Z"
}
GET/v1/links/:uuid

Fetch a single link by its UUID, with the same click analytics as the list endpoint.

Request
$ curl https://api.short-code.io/v1/links/9c3f1e2a-4b7d-4a10-9e2f-6d8c1a5b7e90 \
    -H 'Authorization: Bearer sc_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
Response · 200 OK
{
  "uuid": "9c3f1e2a-4b7d-4a10-9e2f-6d8c1a5b7e90",
  "domain": "srtco.de",
  "title": "Launch page",
  "code": "x9K2mQ7z",
  "named": false,
  "short_url": "https://srtco.de/x9K2mQ7z",
  "destination": "https://acme.com/launch",
  "clicks": {
    "count": { "total": 128, "day": 3, "week": 24, "month": 97 },
    "by_day": [
      { "date": "2026-07-17", "clicks": 21 },
      { "date": "2026-07-18", "clicks": 3 }
    ],
    "by_origin": { "DE": 67, "US": 33 }
  },
  "created": "2026-06-02T09:14:22.000Z",
  "updated": "2026-07-18T15:02:11.000Z"
}
PATCH/v1/links/:uuid

Update a link's destination, and optionally its title. destination is required and must be a valid http(s) URL. title is optional: omit it to keep the current one, or send null or "" to remove it. The short code is immutable: sending a code that differs from the current one returns 400 invalid_request, so a read-modify-write round trip is safe.

Request
$ curl -X PATCH https://api.short-code.io/v1/links/9c3f1e2a-4b7d-4a10-9e2f-6d8c1a5b7e90 \
    -H 'Authorization: Bearer sc_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' \
    -H 'Content-Type: application/json' \
    -d '{ "destination": "https://acme.com/summer-sale" }'
Response · 200 OK
{
  "uuid": "9c3f1e2a-4b7d-4a10-9e2f-6d8c1a5b7e90",
  "domain": "srtco.de",
  "title": "Launch page",
  "code": "x9K2mQ7z",
  "named": false,
  "short_url": "https://srtco.de/x9K2mQ7z",
  "destination": "https://acme.com/summer-sale",
  "clicks": {
    "count": { "total": 128, "day": 3, "week": 24, "month": 97 },
    "by_day": [
      { "date": "2026-07-17", "clicks": 21 },
      { "date": "2026-07-18", "clicks": 3 }
    ],
    "by_origin": { "DE": 67, "US": 33 }
  },
  "created": "2026-06-02T09:14:22.000Z",
  "updated": "2026-07-23T10:52:47.000Z"
}
DELETE/v1/links/:uuid

Permanently delete a link. Existing short URLs stop resolving immediately.

Request
$ curl -X DELETE https://api.short-code.io/v1/links/9c3f1e2a-4b7d-4a10-9e2f-6d8c1a5b7e90 \
    -H 'Authorization: Bearer sc_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
Response · 204 No Content
(empty body)

MCP server

Connect AI agents to your account over the Model Context Protocol. The server is stateless Streamable HTTP, speaks JSON only, and authenticates with the same API keys as the REST API (paid plans only). Every tool call counts against the same rate limit as a REST request.

Endpoint:

https://api.short-code.io/mcp

Claude Code:

$ claude mcp add --transport http short-code https://api.short-code.io/mcp \
    --header "Authorization: Bearer YOUR_API_KEY"

Tools: list_links, create_link, get_link, update_link, delete_link, get_link_qr, list_qr_templates, get_link_stats, list_domains. Tool errors carry the same machine-readable codes as the REST API's error envelope.

Keys are secrets here too. An agent with your API key can create, change, and delete links on your account. Use a dedicated key per agent so you can revoke it on its own.

Errors

Every non-2xx response has the same JSON envelope:

{
  "error": {
    "code": "invalid_request",
    "message": "destination is required and must be a valid http(s) URL"
  }
}
StatusCodeWhen it happens
401unauthorizedMissing, invalid, or revoked API key.
403forbiddenThe account is on the free plan; API access requires a paid plan.
403plan_limit_reachedPOST /v1/links would exceed the account's link limit, or its named-link allowance on the shared domain.
400invalid_requestdestination is missing or not a valid http(s) URL; or code is malformed, reserved or disallowed on the shared domain; or title is not a string of at most 120 characters; or a PATCH tried to change code.
400blocked_destinationdestination is listed on a spam or phishing blocklist. The link was not created or updated.
400redirector_destinationdestination is another URL shortener, or a domain served by short-code.io. Redirect chains are refused; link to the page it leads to instead.
409code_takenThe requested code is already in use on that domain.
404not_foundThe link (or, for domain on create, the domain) doesn't exist or isn't accessible to your account.
429rate_limitedToo many requests; see rate limits below.

Rate limits

Requests are limited per account over a rolling 60-second interval:

PlanRequests / minute
Pro60
Enterprise600

Every authenticated response includes these headers:

HeaderMeaning
X-RateLimit-LimitRequests allowed in any rolling 60-second interval for your plan.
X-RateLimit-RemainingRequests still available in the active rolling interval.
X-RateLimit-ResetThe relevant quota refresh time as a Unix epoch timestamp (seconds). On a 429, this is when another request can be accepted.

If you exceed your limit, the request is rejected with 429 rate_limited and a Retry-After header (seconds until you can retry).