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 API | High-volume API | |
|---|---|---|
| Base URL | api.rebrandly.com | enterprise-api.rebrandly.com |
| Links per request | 1 | Up to 25 |
| Default rate limit | 10 req/sec | 1 req/sec |
| Effective link throughput | 10 links/sec | 25 links/sec |
| Max rate limit (enhanced) | 10 req/sec | up to 40 req/sec |
| TTL (expiration) | Optional | Mandatory (max 90 days) |
| Appears in dashboard | Yes | No—API only |
| API calls/hour (default) | 36,000 | 3,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
| Configuration | Requests/sec | Links/request | Links/sec | Links/min | Links/hr |
|---|---|---|---|---|---|
| Default | 1 | 25 | 25 | 1,500 | 90,000 |
| Enhanced (example) | 40 | 25 | 1,000 | 60,000 | 3,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:
| Header | Description |
|---|---|
X-rate-limit-remaining | Requests remaining in the current time window |
X-rate-limit-first-expire | When the earliest request in the window expires |
X-rate-limit-reset | When 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
- High-volume hosts and routing—dual-host behavior and WAF quirk
- High-volume API link limitations—silently dropped fields
- API rate limits—full rate limit reference
- Troubleshooting—common errors and fixes
