API
Bulk Generate Short Links via the REST API
Need to create dozens, hundreds, or thousands of short links at once? URL Shortify PRO's bulk REST endpoint (POST /links/bulk) creates them all in a single authenticated request, validating each link independently so one bad row doesn't fail the batch. This guide covers how to enable the endpoint, authenticate, format your payload, and handle payloads larger than the default batch limit.
PRO feature
The bulk endpoint is part of URL Shortify PRO and is switched off by default. You must enable it under Settings → API → Bulk API before it will accept requests. The free version's REST API creates one link per request via POST /links — see the API Reference.
Endpoint
POST /wp-json/url-shortify/v1/links/bulk
Creates multiple short links in one request. Each link in the payload is validated and created independently — one bad row doesn't fail the whole batch, and you get a status for every input.
Enable the bulk endpoint
The bulk endpoint is switched off by default. Until you enable it, every request returns HTTP 403 even with perfectly valid credentials.
- Go to URL Shortify → Settings → API → Bulk API.
- Turn on Enable Bulk API.
- Save the settings.
Authentication
The bulk endpoint accepts two authentication methods. Pick whichever fits your environment.
Option A — Custom Headers (Recommended)
X-URL-SHORTIFY-CONSUMER-KEY: ck_live_xxxxxxxxxxxx
X-URL-SHORTIFY-CONSUMER-SECRET: cs_live_xxxxxxxxxxxx
Option B — HTTP Basic Auth
Authorization: Basic base64(consumer_key:consumer_secret)
Generating API Keys
API keys are managed on the Tools screen, not the Settings page:
- Go to URL Shortify → Tools → REST API.
- Click Add API Key.
- Enter a Description (e.g. "Content sync bot"), choose the User the key acts as, and set Permissions to Write or Read & Write — bulk creation needs write access.
- Save, then copy the Consumer Key and Consumer Secret — the secret is shown only once.
Store the credentials in your environment variables or a secrets manager. Never commit them to source control.
Request Body
Send a JSON object with a links array. Each item describes one short link.
{
"links": [
{
"url": "https://example.com/products/blue-widget",
"slug": "blue-widget",
"title": "Blue Widget Product Page",
"group_id": 7,
"tags": [3, 12],
"expiration_date": "2026-12-31T23:59:59Z"
},
{
"url": "https://example.com/products/red-widget",
"slug": "red-widget",
"title": "Red Widget Product Page"
},
{
"url": "https://example.com/products/green-widget"
}
]
}
Field Reference
| Field | Type | Required | Notes |
|---|---|---|---|
url |
string (URL) | yes | The destination URL. Must include the scheme (https://). |
slug |
string | no | Custom short slug. URL Shortify auto-generates a unique slug if you leave it empty. |
title |
string | no | Human-readable name for the link, shown in the admin. |
group_id |
integer | no | Numeric ID of an existing group. Use GET /groups to look up IDs. |
tags |
integer[] | no | Array of existing tag IDs. |
expiration_date |
ISO-8601 string | no | Date/time after which the link stops redirecting. |
The endpoint also accepts these aliases, so payloads written for other tools usually work unchanged:
| Alias | Equivalent to | Notes |
|---|---|---|
group_ids |
group_id |
An array; only the first ID is used. |
tag_ids |
tags |
Identical behaviour. |
expires_at |
expiration_date |
Identical behaviour. |
Response
A successful bulk request returns HTTP 201 with a per-item status array:
{
"success": true,
"data": [
{
"original_url": "https://example.com/products/blue-widget",
"short_url": "https://yoursite.com/blue-widget",
"slug": "blue-widget",
"status": "created"
},
{
"original_url": "https://example.com/products/red-widget",
"short_url": "https://yoursite.com/red-widget",
"slug": "red-widget",
"status": "created"
},
{
"original_url": "https://example.com/products/green-widget",
"short_url": "https://yoursite.com/abc123",
"slug": "abc123",
"status": "created"
}
]
}
If an individual link fails validation, that single item carries a status of error and a message. The rest of the batch still gets created.
{
"original_url": "not-a-valid-url",
"status": "error",
"message": "Invalid URL."
}
Batch Size Limits
By default, the bulk endpoint accepts up to 50 links per request. You can raise or lower this limit:
- Go to URL Shortify → Settings → API → Bulk API.
- Set Bulk Request Limit to the maximum you need.
- Save.
If you send more than the configured limit, the whole request returns HTTP 400 with a clear message — none of the links are created. Stay below the limit, or split your payload into multiple requests.
Tip for very large migrations: Send batches of 50 in a loop with a short delay between them. This gives your server breathing room and keeps individual requests under typical PHP/proxy timeout limits.
Working Examples
cURL
curl -X POST 'https://yoursite.com/wp-json/url-shortify/v1/links/bulk' \
-H 'Content-Type: application/json' \
-H "X-URL-SHORTIFY-CONSUMER-KEY: $US_KEY" \
-H "X-URL-SHORTIFY-CONSUMER-SECRET: $US_SECRET" \
-d '{
"links": [
{ "url": "https://example.com/a", "slug": "promo-a" },
{ "url": "https://example.com/b", "slug": "promo-b" }
]
}'
Python
import os
import requests
KEY = os.environ['US_KEY']
SECRET = os.environ['US_SECRET']
resp = requests.post(
'https://yoursite.com/wp-json/url-shortify/v1/links/bulk',
headers={
'X-URL-SHORTIFY-CONSUMER-KEY': KEY,
'X-URL-SHORTIFY-CONSUMER-SECRET': SECRET,
},
json={
'links': [
{'url': 'https://example.com/a', 'slug': 'promo-a'},
{'url': 'https://example.com/b', 'slug': 'promo-b'},
]
},
timeout=30,
)
resp.raise_for_status()
for item in resp.json()['data']:
print(f"{item['status']:<8} {item.get('short_url', item.get('message'))}")
Node.js (axios)
const axios = require('axios');
const { US_KEY, US_SECRET } = process.env;
async function bulkCreate(links) {
const response = await axios.post(
'https://yoursite.com/wp-json/url-shortify/v1/links/bulk',
{ links },
{
headers: {
'X-URL-SHORTIFY-CONSUMER-KEY': US_KEY,
'X-URL-SHORTIFY-CONSUMER-SECRET': US_SECRET,
},
}
);
return response.data.data;
}
bulkCreate([
{ url: 'https://example.com/a', slug: 'promo-a' },
{ url: 'https://example.com/b', slug: 'promo-b' },
]).then(console.log);
Common Use Cases
- CSV-style migrations. Read rows from a spreadsheet or external system and POST them in batches of 50.
- Content publishing pipelines. When your CMS publishes new posts, automatically create a tracked short link for sharing.
- E-commerce catalogs. Generate a short link for every product on import or sync.
- Email campaign builders. Create a unique short link per recipient (or per cohort) for granular click tracking.
- Affiliate networks. Programmatically generate creator-specific short links with pre-assigned tags and groups.
Best Practices
- Always set a
slugwhen you can predict the destination. Auto-generated slugs are fine, but predictable ones make external systems easier to reason about. - Validate URLs before sending. Saves round-trips and keeps the response array clean.
- Handle partial failures. Iterate the response and retry only the items with
status: error— don't re-send the whole batch. - Watch the rate. If you're bulk-creating thousands of links, throttle to one request per second to stay friendly to your server.
- Use distinct API keys per integration. If you have multiple systems creating links, give each its own key so you can revoke one without affecting the others.
Conclusion
The bulk endpoint turns URL Shortify PRO into a programmable link factory: enable it under Settings → API, authenticate with a write-enabled API key, and POST an array of links to create thousands in batches of up to your configured limit. For single-link calls and the full endpoint list, see the API Reference; to bulk-create links from existing content without code, use Bulk Generate Short Links from Posts & Pages.
FAQs
Is the bulk API available in the free version?
No. The /links/bulk endpoint is a URL Shortify PRO feature and is disabled by default even in PRO — you enable it under Settings → API → Bulk API. The free REST API can still create links one at a time with POST /links. If you send bulk requests without PRO, or before enabling the endpoint, you get an HTTP 403 response.
How many links can I create in one request?
By default the bulk endpoint accepts up to 50 links per request, set by Bulk Request Limit under Settings → API → Bulk API. You can raise or lower it there. Sending more links than the configured limit returns HTTP 400 and creates none of them, so split large jobs into batches at or below your limit.
What happens if one link in the batch is invalid?
Only that link fails. Each item is validated and created independently, so an invalid URL comes back with a status of error and a message, while every valid link in the same request is still created with a status of created. Iterate the response array and retry only the items that errored — don't resend the whole batch.
Which authentication should I use for server-to-server calls?
Either works, but custom headers are recommended: send X-URL-SHORTIFY-CONSUMER-KEY and X-URL-SHORTIFY-CONSUMER-SECRET with each request. HTTP Basic Auth (Consumer Key as username, Consumer Secret as password) is the alternative for clients that don't set custom headers easily. The key must have Write or Read & Write permission to create links.
Can I assign groups and tags during bulk creation?
Yes. Each link object accepts a group_id (or the group_ids array, of which only the first ID is used) and a tags array of existing tag IDs (tag_ids is an accepted alias). Look up group IDs with GET /groups first. Groups are available in the free plugin; tags are a PRO feature, which fits since the bulk endpoint is PRO-only.
Related
- API Reference — full endpoint and authentication reference
- Bulk Generate Short Links from Posts & Pages — UI-driven bulk generation
- Organise Links with Groups — create the groups you reference by ID