Creating links at scale for SMS and campaigns

How to use the Rebrandly high-volume API to batch-create branded links for SMS campaigns, transactional email, and other high-throughput integrations.

The Rebrandly high-volume API runs on a dedicated host, enterprise-api.rebrandly.com, tuned for batch link creation at scale. It supports batch creation of up to 25 links per API call with a dedicated base URL and a different rate-limit model optimized for batch throughput—designed for SMS senders, transactional email platforms, and any integration that creates links at campaign scale.

This unique API provides the infrastructure to create branded links in bulk. If you're evaluating Rebrandly for high-volume use, this is the feature you need to understand first.

How the high-volume API differs from the Rebrandly API

Rebrandly APIHigh-volume API
Base URLapi.rebrandly.comenterprise-api.rebrandly.com
Links per request1Up to 25
Default rate limit10 req/sec1 req/sec
Effective link throughput10 links/sec25 links/sec
Max rate limit (enhanced)10 req/secup to 40 req/sec
TTL (expiration)OptionalMandatory (max 90 days)
Appears in dashboardYesNo—API only
API calls/hour (default)36,0003,600

Important constraints

Before architecting your integration, note these high-volume API constraints:

TTL is mandatory. Every link must have an expiration, set via the ttl parameter (in seconds) at creation time. The range is 3,600 seconds (1 hour) to 7,776,000 seconds (90 days). If you pass a value exceeding your plan's maximum, it is silently capped and the response includes ttlCapped. Links are deleted automatically when they expire. Design your system to handle link expiration—for example, pre-generate links close to send time or build logic to refresh expiring links.

If you do not pass ttl, the workspace-level default applies. The expiration date is returned as expiresAt in the response.

Links are API-only. Branded links do not appear in the Rebrandly dashboard. They are accessible only via API using the id returned at creation time. Store this id in your own data store.

Different base URL and workspace header. High-volume link creation uses enterprise-api.rebrandly.com, not api.rebrandly.com. All requests must also include your workspace ID as a request header:

workspace: YOUR_WORKSPACE_ID

Both hosts work for retrieving existing high-volume links, but only enterprise-api.rebrandly.com provides the high-rate-limit cluster. See API hosts and routing for details.

Rate limit is per request, not per link. The default 1 req/sec limit applies to PUT calls, each carrying up to 25 links. Effective default throughput is therefore 25 links/sec, not 1 link/sec.

Throughput reference

ConfigurationRequests/secLinks/requestLinks/secLinks/minLinks/hr
Default125251,50090,000
Enhanced (example)40251,00060,0003,600,000

To inquire about higher rate limits, contact us.

Throughput figures assume sustained requests at the rate limit. Real-world latency will vary.

Monthly/annual link ceiling: The number of links you can create per month or year is defined in your subscription plan contract.

Creating a batch of branded links

Request

Send a PUT request to enterprise-api.rebrandly.com/v1/links with an array of link objects. Include your workspace ID in the request header:

curl -X PUT https://enterprise-api.rebrandly.com/v1/links \
  -H "Content-Type: application/json" \
  -H "apikey: YOUR_API_KEY" \
  -H "workspace: YOUR_WORKSPACE_ID" \
  -d '[
    {
      "destination": "https://www.brandyour.link/product?ref=sms_001",
      "title": "SMS link 001",
      "ttl": 2592000
    },
    {
      "destination": "https://www.brandyour.link/product?ref=sms_002",
      "title": "SMS link 002",
      "ttl": 2592000
    }
  ]'
// Node.js—batch create high-volume links
const HIGH_VOLUME_API = "https://enterprise-api.rebrandly.com";
const API_KEY = process.env.REBRANDLY_API_KEY;
const WORKSPACE_ID = process.env.REBRANDLY_WORKSPACE_ID;

async function createCampaignLinks(links) {
  const response = await fetch(`${HIGH_VOLUME_API}/v1/links`, {
    method: "PUT",
    headers: {
      "Content-Type": "application/json",
      "apikey": API_KEY,
      "workspace": WORKSPACE_ID
    },
    body: JSON.stringify(links)
  });

  if (!response.ok) {
    throw new Error(`API error: ${response.status}`);
  }

  return response.json();
}

// Create a batch of 25 links — TTL set to 30 days (in seconds)
const TTL_30_DAYS = 30 * 24 * 60 * 60;
const batch = Array.from({ length: 25 }, (_, i) => ({
  destination: `https://www.brandyour.link/product?ref=sms_${String(i + 1).padStart(3, "0")}`,
  title: `SMS link ${i + 1}`,
  ttl: TTL_30_DAYS
}));

const createdLinks = await createCampaignLinks(batch);
console.log(`Created ${createdLinks.length} links`);
import os
import requests

HIGH_VOLUME_API = "https://enterprise-api.rebrandly.com"
API_KEY = os.environ["REBRANDLY_API_KEY"]
WORKSPACE_ID = os.environ["REBRANDLY_WORKSPACE_ID"]
HEADERS = {
    "Content-Type": "application/json",
    "apikey": API_KEY,
    "workspace": WORKSPACE_ID
}

TTL_30_DAYS = 30 * 24 * 60 * 60  # seconds

def create_campaign_links(links: list[dict]) -> list[dict]:
    response = requests.put(
        f"{HIGH_VOLUME_API}/v1/links",
        headers=HEADERS,
        json=links
    )
    response.raise_for_status()
    return response.json()

# Build a batch of 25 links
batch = [
    {
        "destination": f"https://www.brandyour.link/product?ref=sms_{str(i+1).zfill(3)}",
        "title": f"SMS link {i+1}",
        "ttl": TTL_30_DAYS
    }
    for i in range(25)
]

links = create_campaign_links(batch)
print(f"Created {len(links)} links")
for link in links:
    print(link["shortUrl"])

Response

Returns an array of created link objects. Store the id of each—it is the only way to retrieve or manage a link later.

When the ttl value is within your plan limit:

[
  {
    "id": "a1b2c3d4e5f6",
    "shortUrl": "rebrand.ly/abc001",
    "destination": "https://www.brandyour.link/product?ref=sms_001",
    "ttl": 2592000,
    "expiresAt": "2026-09-01T00:00:00.000Z",
    "ttlCapped": null,
    "status": "active"
  }
]

When the ttl value exceeds your plan's maximum, it is silently capped and ttlCapped is returned with details:

[
  {
    "id": "a1b2c3d4e5f6",
    "shortUrl": "rebrand.ly/abc001",
    "destination": "https://www.brandyour.link/product?ref=sms_001",
    "ttl": 7776000,
    "expiresAt": "2026-09-01T00:00:00.000Z",
    "ttlCapped": {
      "requestedValue": 31536000,
      "appliedValue": 7776000,
      "reason": "plan_max_exceeded"
    },
    "status": "active"
  }
]

High-volume batch creation pattern

For campaigns requiring more than 25 links, split your URLs into batches and send them sequentially at the rate limit:

// Node.js—rate-limited batch processor
function chunk(array, size) {
  const chunks = [];
  for (let i = 0; i < array.length; i += size) {
    chunks.push(array.slice(i, i + size));
  }
  return chunks;
}

function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

async function createLinksAtScale(destinations, ttl) {
  const batches = chunk(destinations, 25);
  const allLinks = [];

  for (let i = 0; i < batches.length; i++) {
    const batch = batches[i];
    const links = batch.map((destination) => ({
      destination,
      ttl
    }));

    const created = await createCampaignLinks(links);
    allLinks.push(...created);

    // Respect default 1 req/sec rate limit
    if (i < batches.length - 1) {
      await sleep(1000);
    }
  }

  return allLinks;
}

Rate limit headers

Every API response includes rate limit headers:

HeaderDescription
X-rate-limit-remainingRequests remaining in the current time window
X-rate-limit-first-expireWhen the earliest request in the window expires
X-rate-limit-resetWhen the current window resets

If you receive a 429 Too Many Requests response, read X-rate-limit-reset to determine when to retry.

Use case: SMS branded link generation

A common pattern for SMS platforms: generate unique trackable links for each recipient immediately before send.

// Generate one tracked link per SMS recipient
async function prepareSmsCampaign(recipients, campaignUrl, ttlSeconds) {
  const destinations = recipients.map(
    r => `${campaignUrl}?recipient_id=${r.id}&utm_source=sms`
  );

  const links = await createLinksAtScale(
    destinations,
    ttlSeconds
  );

  // Pair each recipient with their unique short link
  return recipients.map((r, i) => ({
    ...r,
    trackingUrl: links[i].shortUrl
  }));
}

// Example: campaign links expiring in 7 days
const TTL_7_DAYS = 7 * 24 * 60 * 60;
const campaignLinks = await prepareSmsCampaign(recipients, campaignUrl, TTL_7_DAYS);

Feature limitations on high-volume links

Several Rebrandly API features are not supported when creating bulk links using the high-volume API at enterprise-api.rebrandly.com. See High-volume API link limitations for a full list of fields that are accepted but silently dropped.

Related pages