Skip to content
EndURL

Developers

Link infrastructure, programmable

Everything the dashboard does, the REST API does too — with scoped keys, idempotency, consistent errors and an OpenAPI document generated straight from the implementation's schemas.

Authentication

Create a key in Settings → API keys, choose its scopes, and send it as a bearer token. Secrets are shown once and stored only as SHA-256 hashes; keys can be rotated or revoked at any time.

Authorization: Bearer eul_xxxxxxxxxxxxxxxx

Quick start

cURL

curl -X POST https://endurl.com/api/v1/links \
  -H "Authorization: Bearer $ENDURL_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: launch-2026" \
  -d '{"destination": "https://example.com/launch", "alias": "launch"}'

JavaScript / TypeScript

const res = await fetch("https://endurl.com/api/v1/links", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.ENDURL_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    destination: "https://example.com/launch",
    alias: "launch",
  }),
});
const link = await res.json();
console.log(link.shortUrl); // https://endurl.com/launch

Python

import os, requests

res = requests.post(
    "https://endurl.com/api/v1/links",
    headers={"Authorization": f"Bearer {os.environ['ENDURL_API_KEY']}"},
    json={"destination": "https://example.com/launch", "alias": "launch"},
)
print(res.json()["shortUrl"])  # https://endurl.com/launch

Endpoints

MethodPathDescription
POST/linksCreate a short link
GET/linksList links (cursor pagination, filters)
GET/links/{id}Get one link
PATCH/links/{id}Update destination, tags, expiry, rules
DELETE/links/{id}Delete (tombstones the alias)
POST/links/{id}/archiveArchive a link
POST/links/{id}/restoreRestore an archived link
GET/links/{id}/analyticsSummary, timeline and breakdowns
GET/meKey + organization info
GET/usageCurrent usage vs plan limits

Domains, bulk, webhooks and conversion-event endpoints ship with their product phases and appear in the OpenAPI document as they land.

Errors

{
  "error": {
    "code": "ALIAS_ALREADY_EXISTS",
    "message": "The requested alias is already in use.",
    "requestId": "req_8f2c1a9d4b7e"
  }
}

Machine-readable codes, human-readable messages, and a request ID on every response for support correlation.

Rate limits & idempotency

Responses carry X-RateLimit-Limit, -Remaining and -Reset; exceeding a limit returns 429 with Retry-After.

Send an Idempotency-Key header on creates — retries within 24 hours return the original result instead of duplicating work.