Overview
Bulk operations allow you to create or delete up to 100 links in a single API request. This is perfect for:
Launching marketing campaigns with many variations
Migrating links from another service
Cleaning up expired campaign links
Automating link generation at scale
Bulk Create Links
Create up to 100 links in one request using POST /v1/links/bulk.
Basic Example
curl -X POST https://api.bouncy.ai/v1/links/bulk \
-H "X-Api-Key: bcy_live_pk_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"links": [
{
"url": "https://example.com/page1",
"slug": "page1",
"title": "Page 1"
},
{
"url": "https://example.com/page2",
"slug": "page2",
"title": "Page 2"
},
{
"url": "https://example.com/page3",
"slug": "page3",
"title": "Page 3"
}
]
}'
{
"created" : [
{
"id" : "link_abc123" ,
"shortUrl" : "https://bouncy.link/page1" ,
"slug" : "page1" ,
"destination" : "https://example.com/page1"
},
{
"id" : "link_def456" ,
"shortUrl" : "https://bouncy.link/page2" ,
"slug" : "page2" ,
"destination" : "https://example.com/page2"
}
],
"failed" : [
{
"index" : 2 ,
"slug" : "page3" ,
"error" : {
"code" : "slug_already_exists" ,
"message" : "The slug 'page3' is already in use"
}
}
],
"summary" : {
"total" : 3 ,
"succeeded" : 2 ,
"failed" : 1
}
}
Response Fields :
created - Array of successfully created links
failed - Array of links that failed with error details
summary - Count of total, succeeded, and failed operations
Partial success is supported - if some links fail, the successful ones are still created.
Real-World Examples
Marketing Campaign with UTM Parameters
Generate 50 links for a social media campaign across platforms:
const platforms = [ 'facebook' , 'instagram' , 'twitter' , 'linkedin' , 'tiktok' ];
const contentTypes = [ 'story' , 'post' , 'ad' , 'carousel' ];
const links = [];
platforms . forEach ( platform => {
contentTypes . forEach ( type => {
links . push ({
url: `https://example.com/campaign?utm_source= ${ platform } &utm_medium= ${ type } &utm_campaign=summer2026` ,
slug: `summer- ${ platform } - ${ type } ` ,
title: `Summer Campaign - ${ platform } ${ type } ` ,
tags: [ 'summer2026' , platform , type ]
});
});
});
const response = await fetch ( 'https://api.bouncy.ai/v1/links/bulk' , {
method: 'POST' ,
headers: {
'X-Api-Key' : 'bcy_live_pk_YOUR_API_KEY' ,
'Content-Type' : 'application/json'
},
body: JSON . stringify ({ links })
});
Import from CSV
Read links from a CSV file and bulk create:
import fs from 'fs' ;
import csvParser from 'csv-parser' ;
const links = [];
fs . createReadStream ( 'links.csv' )
. pipe ( csvParser ())
. on ( 'data' , ( row ) => {
links . push ({
url: row . destination ,
slug: row . slug ,
title: row . title ,
tags: row . tags ?. split ( ',' ) || []
});
})
. on ( 'end' , async () => {
// Process in batches of 100
for ( let i = 0 ; i < links . length ; i += 100 ) {
const batch = links . slice ( i , i + 100 );
const response = await fetch ( 'https://api.bouncy.ai/v1/links/bulk' , {
method: 'POST' ,
headers: {
'X-Api-Key' : 'bcy_live_pk_YOUR_API_KEY' ,
'Content-Type' : 'application/json'
},
body: JSON . stringify ({ links: batch })
});
const result = await response . json ();
console . log ( `Batch ${ i / 100 + 1 } : Created ${ result . created . length } , Failed ${ result . failed . length } ` );
}
});
Bulk Delete Links
Delete up to 100 links in one request using DELETE /v1/links/bulk.
Example
curl -X DELETE https://api.bouncy.ai/v1/links/bulk \
-H "X-Api-Key: bcy_live_pk_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"linkIds": ["link_abc123", "link_def456", "link_ghi789"]
}'
Response
{
"deleted" : [ "link_abc123" , "link_def456" ],
"failed" : [
{
"linkId" : "link_ghi789" ,
"error" : {
"code" : "link_not_found" ,
"message" : "Link not found"
}
}
],
"summary" : {
"total" : 3 ,
"succeeded" : 2 ,
"failed" : 1
}
}
Delete Links by Tag
Combine GET /v1/links with bulk delete to remove all links with a specific tag:
// Step 1: Get all links with tag "expired"
const response = await fetch ( 'https://api.bouncy.ai/v1/links?tag=expired&limit=100' , {
headers: { 'X-Api-Key' : 'bcy_live_pk_YOUR_API_KEY' }
});
const { data : links } = await response . json ();
const linkIds = links . map ( link => link . id );
// Step 2: Bulk delete
if ( linkIds . length > 0 ) {
const deleteResponse = await fetch ( 'https://api.bouncy.ai/v1/links/bulk' , {
method: 'DELETE' ,
headers: {
'X-Api-Key' : 'bcy_live_pk_YOUR_API_KEY' ,
'Content-Type' : 'application/json'
},
body: JSON . stringify ({ linkIds })
});
const result = await deleteResponse . json ();
console . log ( `Deleted ${ result . deleted . length } expired links` );
}
Best Practices
Batch size limit: 100 links
The API accepts a maximum of 100 links per request. For larger operations, split into multiple batches: async function bulkCreateAll ( links ) {
const batchSize = 100 ;
const results = [];
for ( let i = 0 ; i < links . length ; i += batchSize ) {
const batch = links . slice ( i , i + batchSize );
const response = await fetch ( 'https://api.bouncy.ai/v1/links/bulk' , {
method: 'POST' ,
headers: {
'X-Api-Key' : 'bcy_live_pk_YOUR_API_KEY' ,
'Content-Type' : 'application/json'
},
body: JSON . stringify ({ links: batch })
});
const result = await response . json ();
results . push ( result );
}
return results ;
}
Always check the failed array in the response: const result = await response . json ();
if ( result . failed . length > 0 ) {
console . error ( ` ${ result . failed . length } links failed:` );
result . failed . forEach ( failure => {
console . error ( ` - Slug " ${ failure . slug } ": ${ failure . error . message } ` );
});
}
console . log ( `Successfully created ${ result . created . length } links` );
Rate limits apply per request
Each bulk request counts as 1 request toward your rate limit, regardless of how many links are in it. This makes bulk operations very efficient! Example: Creating 100 links individually = 100 requests. Creating 100 links with bulk = 1 request.
Add delays between batches
When processing multiple batches, add a small delay to avoid overwhelming the API: for ( const batch of batches ) {
await createBatch ( batch );
await new Promise ( resolve => setTimeout ( resolve , 1000 )); // 1 second delay
}
Error Handling
Quota Exceeded
If you exceed your plan’s link limit, the entire bulk request fails:
{
"error" : {
"code" : "quota_exceeded" ,
"message" : "Creating 100 links would exceed your plan limit (950/1000 used)" ,
"currentLinks" : 950 ,
"requestedLinks" : 100 ,
"maxLinks" : 1000
}
}
Solution : Delete unused links or upgrade your plan .
Some Links Failed
If individual links fail validation, they appear in the failed array:
{
"created" : [ ... ],
"failed" : [
{
"index" : 0 ,
"slug" : "invalid-url" ,
"error" : {
"code" : "invalid_url" ,
"message" : "The URL must be a valid HTTP or HTTPS URL"
}
}
]
}
Fix the invalid links and retry only the failed ones.
Next Steps