Rate Limits

Every API endpoint has rate limits to ensure fair usage and platform stability. Rate limits are applied per IP address using a sliding window.

Endpoint Limits

EndpointMethodLimitWindow
POST /api/linksCreate link10 req1 min
GET /api/linksList links30 req1 min
GET /api/links/:idGet link60 req1 min
PATCH /api/links/:idUpdate link10 req1 min
DELETE /api/links/:idDelete link10 req1 min
GET /api/links/:id/clicksClick analytics30 req1 min
POST /api/shortenQuick shorten (auth)30 req1 min
POST /api/shortenQuick shorten (anon)5 req1 min
GET /api/keysList keys30 req1 min
POST /api/keysCreate key10 req1 min
DELETE /api/keys/:idRevoke key10 req1 min
GET /api/webhooksList webhooks30 req1 min
POST /api/webhooksCreate webhook10 req1 min
PATCH /api/webhooks/:idUpdate webhook10 req1 min
DELETE /api/webhooks/:idDelete webhook10 req1 min
POST /api/webhooks/:idTest ping5 req1 min
GET /api/domainsList domains30 req1 min
POST /api/domains/addAdd domain10 req1 min
POST /api/domains/:id/verifyVerify domain5 req1 min
DELETE /api/domains/:idDelete domain10 req1 min
PATCH /api/domains/:idUpdate domain10 req1 min

Response Headers

When you hit the rate limit, the response includes a Retry-After header:

FieldTypeDescription
Retry-AfternumberSeconds to wait before retrying

The /api/shorten endpoint also returns these headers on all responses:

FieldTypeDescription
X-RateLimit-LimitnumberMaximum requests allowed in the window
X-RateLimit-RemainingnumberRequests remaining in the current window
X-RateLimit-ResetnumberSeconds until the window resets

Handling 429 Responses

When rate limited, you receive a 429 status with this body:

429 Too Many Requests
{
  "error": "Too many requests"
}

// Headers:
// Retry-After: 45

Best Practices

Exponential Backoff (TypeScript)
async function apiCallWithRetry(fn: () => Promise<Response>, maxRetries = 3) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    const res = await fn();

    if (res.status === 429) {
      const retryAfter = parseInt(res.headers.get('Retry-After') || '60');
      console.log(`Rate limited. Retrying in ${retryAfter}s...`);
      await new Promise(r => setTimeout(r, retryAfter * 1000));
      continue;
    }

    return res;
  }

  throw new Error('Max retries exceeded');
}

Tips for Staying Within Limits

  • Cache responses: List results and link data can be cached on your end to reduce API calls
  • Use webhooks for real-time data, Instead of polling for click events, subscribe to link.click webhooks
  • Batch operations in the dashboard, The dashboard supports bulk operations (import, export, tag) without counting against API limits
  • Use pagination efficiently, Fetch larger pages (up to 100 items) instead of many small pages
  • Respect Retry-After, Always wait the specified time before retrying, or you risk progressive penalties

Was this page helpful? Spotted something wrong?