Skip to content

API reference

HTTP API.

Create links and read their stats from your own code: JSON over HTTPS with a personal token. Included in Free.

Base URL
https://api.dwnl.cc/v1
Auth
Bearer token
Format
JSON, camelCase

Basics

Authentication

Every request carries a personal token in the Authorization header. Create one on the Developers page of the app and pick its scopes; the secret is shown once, so store it as one. Revoke a token on the same page and it stops working at once.

Scopes

links:read
List and read links
links:write
Create, edit and delete links
stats:read
Read click stats
traffic:read
Read sources, offers, campaigns, conversions (Pro)
traffic:write
Change them (Pro)

Create a token

Request

curl https://api.dwnl.cc/v1/me \
  -H "Authorization: Bearer $DWNL_TOKEN"

Rate limits

Each token gets 600 requests a minute; the CLI counts as one token per signed-in machine. Every response says how many are left. Over the limit, the API answers 429 and says how long to wait.

Response headers

RateLimit-Limit
Requests allowed in the current minute
RateLimit-Remaining
Requests left in it
RateLimit-Reset
Seconds until it starts over
Retry-After
On a 429 only: seconds to wait

429 Too Many Requests

HTTP/2 429
RateLimit-Limit: 600
RateLimit-Remaining: 0
RateLimit-Reset: 12
Retry-After: 12

{
  "code": "rate_limited",
  "detail": "600 requests per minute per token. Retry after 12 s."
}

Errors

A failed request returns a 4xx or 5xx status and a JSON body: a stable code to branch on and a sentence for people.

StatusCodeWhen
400invalid_requestThe body is not JSON, or a field has the wrong type
401unauthorizedNo token, or an expired or revoked one
403insufficient_scopeThe token lacks the scope this call needs
404not_foundNo link with that code in your account
409code_takenThe back-half you asked for is in use
422invalid_urlThe URL is not http(s), has spaces or points to dwnl.cc
429rate_limitedOver the rate limit

404 Not Found

HTTP/2 404

{
  "code": "not_found",
  "detail": "No link with the code a8Kd3xQ."
}

Links

Account

GET/me

Current account

Who the token belongs to, the account's plan and the token's scopes. Works with any valid token, so it is the quick way to check one.

Request

curl https://api.dwnl.cc/v1/me \
  -H "Authorization: Bearer $DWNL_TOKEN"

200 OK

{
  "id": "usr_8f3k2m",
  "name": "Lena Hartmann",
  "email": "lena@example.com",
  "plan": "pro",
  "links": 48,
  "createdAt": "2026-03-02T10:00:00Z",
  "token": {
    "prefix": "dwnl_pat_7Kq2",
    "scopes": ["links:read", "links:write"]
  }
}

Command line

The dwnl CLI

dwnl is a single binary for macOS and Linux that calls this API. It signs in with a device code, so there is no token to paste, and prints only the short link, so its output goes straight into other commands.

dwnl login
Sign in: confirm the code it prints in the browser
dwnl <url>
Shorten a URL and print the short link
dwnl ls
Your links, newest first; --limit and --after page through them
dwnl stats <code>
Clicks for one link; --range 7d|30d|90d, --json
DWNL_TOKEN
A personal token instead of login, e.g. in CI

Terminal

# Install to ~/.local/bin (or: brew install isalikov/tap/dwnl)

curl -fsSL https://raw.githubusercontent.com/isalikov/dwnl/master/scripts/install.sh | sh

# Sign in once

dwnl login

Open https://app.dwnl.cc/developers/cli/device and enter WDJB-MJHT

Signed in as you@example.com

# Shorten and copy

dwnl https://example.com/pricing | pbcopy

# Last week of one link, as JSON

dwnl stats a8Kd3xQ --range 7d --json

# In CI: a personal token instead of login

DWNL_TOKEN="$SECRET" dwnl https://example.com/changelog

https://dwnl.cc/Vt7wP0e

Need a higher rate limit, or the traffic endpoints that come with Pro? Tell us what you are building.

Talk to us