Skip to content
Docs menu

Team and API

Shorten URLs with the API

Create, list, update and delete short links with the Shortener.dev REST API, with examples in cURL, JavaScript and Python.

The Shortener.dev API is a JSON REST API at https://api.shortener.dev/v1. Everything you can do in the link builder, you can do with one POST request, which makes it easy to shorten URLs from a CMS, a newsletter tool, a spreadsheet script or your own app.

You need an API key. The examples read it from a SHORTENER_API_KEY environment variable.

Send the destination as url. Add key for a custom back-half, or leave it out to get a random one:

curl -X POST https://api.shortener.dev/v1/links \
  -H "Authorization: Bearer $SHORTENER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/blog/spring-launch",
    "key": "spring-launch"
  }'

The response is the saved link, with the URL to share in short_url:

{
  "key": "spring-launch",
  "url": "https://example.com/blog/spring-launch",
  "short_url": "https://srt1.link/spring-launch",
  "is_enabled": true,
  "created_at": "2030-03-01T10:00:00Z"
}

The same request in JavaScript:

const response = await fetch('https://api.shortener.dev/v1/links', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.SHORTENER_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    url: 'https://example.com/blog/spring-launch',
    key: 'spring-launch',
  }),
});

if (!response.ok) {
  const { message } = await response.json();
  throw new Error(message);
}

const link = await response.json();
console.log(link.short_url);

And in Python with requests:

import os
import requests

response = requests.post(
    "https://api.shortener.dev/v1/links",
    headers={"Authorization": f"Bearer {os.environ['SHORTENER_API_KEY']}"},
    json={"url": "https://example.com/blog/spring-launch", "key": "spring-launch"},
)
response.raise_for_status()
print(response.json()["short_url"])

Every option in the dashboard is a field on the same request. This one uses all of them:

{
  "url": "https://example.com/shop",
  "key": "summer-shop",
  "expire_at": "2030-08-31T23:59:00Z",
  "params": {
    "utm_source": "newsletter",
    "utm_medium": "email",
    "utm_campaign": "summer_sale"
  },
  "title": "Summer sale, up to 40% off",
  "description": "Our biggest sale of the year ends August 31.",
  "image": "https://example.com/images/summer-og.png",
  "password": "sunny-days",
  "ios": "https://apps.apple.com/us/app/your-app/id000000000",
  "android": "https://play.google.com/store/apps/details?id=com.example.app",
  "geo": [{ "country": "GB", "url": "https://example.co.uk/shop" }]
}
FieldNotes
urlRequired. Must be on a verified or whitelisted domain.
keyCustom back-half, up to 32 characters. Lowercased, with spaces turned into hyphens.
expire_atISO 8601 date-time at least 5 minutes ahead. See expiration.
paramsQuery parameters added to the destination. See UTM parameters.
title, description, imageSocial preview, limited to 60 and 155 characters. See social preview.
passwordUp to 32 characters. See password protection.
ios, androidApp store or deep link URLs. See app targeting.
geoArray of country and url pairs. See geo targeting.
MethodEndpointWhat it does
GET/v1/links?search=spring&limit=50List links, newest first. search matches the exact back-half or part of the destination.
GET/v1/links/{key}Get one link
PUT/v1/links/{key}Update a link's destination or options
DELETE/v1/links/{key}Delete a link permanently

Handle errors

Errors come back with a JSON message that you can show to users or log:

StatusMeaning
400The request is invalid, for example url: Invalid URL or a back-half that's already taken
401The API key is missing or invalid
402Your plan's link limit is reached
403The destination domain isn't verified
429Too many requests. Wait and retry with backoff.

The API reference lists every endpoint, including domains, analytics, reports and team members, and you can send test requests from it.