curl -X POST https://api.bouncy.ai/v1/links/bulk \
-H "Authorization: Bearer bcy_live_pk_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"links": [
{ "url": "https://example.com/page1", "slug": "page1" },
{ "url": "https://example.com/page2", "slug": "page2", "domain": "tapmy.social" },
{ "url": "https://example.com/page3", "slug": "page3" }
]
}'
const response = await fetch('https://api.bouncy.ai/v1/links/bulk', {
method: 'POST',
headers: {
'Authorization': 'Bearer bcy_live_pk_YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
links: [
{ url: 'https://example.com/page1', slug: 'page1' },
{ url: 'https://example.com/page2', slug: 'page2', domain: 'tapmy.social' },
{ url: 'https://example.com/page3', slug: 'page3' }
]
})
});
const result = await response.json();
console.log(`Created ${result.totalCreated} links (${result.inactiveCreated} inactive)`);
import requests
response = requests.post(
'https://api.bouncy.ai/v1/links/bulk',
headers={
'Authorization': 'Bearer bcy_live_pk_YOUR_API_KEY',
'Content-Type': 'application/json'
},
json={
'links': [
{'url': 'https://example.com/page1', 'slug': 'page1'},
{'url': 'https://example.com/page2', 'slug': 'page2', 'domain': 'tapmy.social'},
{'url': 'https://example.com/page3', 'slug': 'page3'}
]
}
)
result = response.json()
print(f"Created {result['totalCreated']} links ({result['inactiveCreated']} inactive)")
{
"success": true,
"message": "Successfully created 3 deeplinks",
"totalCreated": 3,
"activeCreated": 2,
"inactiveCreated": 1,
"links": [
{ "id": "page1", "slug": "page1", "domain": "bouncy.ai", "url": "https://bouncy.ai/page1", "isActive": true },
{ "id": "tapmy.social__page2", "slug": "page2", "domain": "tapmy.social", "url": "https://tapmy.social/page2", "isActive": true },
{ "id": "page3", "slug": "page3", "domain": "bouncy.ai", "url": "https://bouncy.ai/page3", "isActive": false }
]
}
{
"error": "Validation failed",
"details": [
"Row 1: The slug \"admin\" is reserved and cannot be used",
"Row 2: Premium domains like tapmy.social are only available on paid plans. Please upgrade to access premium domains.",
"Row 3: Domain shop.example.com is not verified. Add its DNS records and verify it first.",
"Row 4: Destination URL must be a valid HTTP or HTTPS URL"
]
}
{
"error": "Cannot create 3 deeplinks. This would exceed your total limit of 10. You can create 1 more deeplinks."
}
Links
Bulk Create Links
Create up to 1,000 deeplinks in a single request
POST
/
v1
/
links
/
bulk
curl -X POST https://api.bouncy.ai/v1/links/bulk \
-H "Authorization: Bearer bcy_live_pk_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"links": [
{ "url": "https://example.com/page1", "slug": "page1" },
{ "url": "https://example.com/page2", "slug": "page2", "domain": "tapmy.social" },
{ "url": "https://example.com/page3", "slug": "page3" }
]
}'
const response = await fetch('https://api.bouncy.ai/v1/links/bulk', {
method: 'POST',
headers: {
'Authorization': 'Bearer bcy_live_pk_YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
links: [
{ url: 'https://example.com/page1', slug: 'page1' },
{ url: 'https://example.com/page2', slug: 'page2', domain: 'tapmy.social' },
{ url: 'https://example.com/page3', slug: 'page3' }
]
})
});
const result = await response.json();
console.log(`Created ${result.totalCreated} links (${result.inactiveCreated} inactive)`);
import requests
response = requests.post(
'https://api.bouncy.ai/v1/links/bulk',
headers={
'Authorization': 'Bearer bcy_live_pk_YOUR_API_KEY',
'Content-Type': 'application/json'
},
json={
'links': [
{'url': 'https://example.com/page1', 'slug': 'page1'},
{'url': 'https://example.com/page2', 'slug': 'page2', 'domain': 'tapmy.social'},
{'url': 'https://example.com/page3', 'slug': 'page3'}
]
}
)
result = response.json()
print(f"Created {result['totalCreated']} links ({result['inactiveCreated']} inactive)")
{
"success": true,
"message": "Successfully created 3 deeplinks",
"totalCreated": 3,
"activeCreated": 2,
"inactiveCreated": 1,
"links": [
{ "id": "page1", "slug": "page1", "domain": "bouncy.ai", "url": "https://bouncy.ai/page1", "isActive": true },
{ "id": "tapmy.social__page2", "slug": "page2", "domain": "tapmy.social", "url": "https://tapmy.social/page2", "isActive": true },
{ "id": "page3", "slug": "page3", "domain": "bouncy.ai", "url": "https://bouncy.ai/page3", "isActive": false }
]
}
{
"error": "Validation failed",
"details": [
"Row 1: The slug \"admin\" is reserved and cannot be used",
"Row 2: Premium domains like tapmy.social are only available on paid plans. Please upgrade to access premium domains.",
"Row 3: Domain shop.example.com is not verified. Add its DNS records and verify it first.",
"Row 4: Destination URL must be a valid HTTP or HTTPS URL"
]
}
{
"error": "Cannot create 3 deeplinks. This would exceed your total limit of 10. You can create 1 more deeplinks."
}
Every row is validated before anything is created: if any row fails, nothing is created and the response lists every failing row. The same rules as the dashboard’s bulk creator apply. Two rows that would create the same link (the same slug on the same domain, or the same path on a custom domain) fail as duplicates.
Request
Headers
string
required
Must be
application/jsonBody
array
required
Array of link objects to create (max: 1,000). Each object can contain:
url(required) - Destination URL. Must be a valid HTTP or HTTPS URLslug- Slug for the short URL. Required onbouncy.aiand system domains: 3 to 50 letters, numbers, hyphens and underscores, not a reserved word (for exampleadmin,api,www). On a custom domain it is used as the pathdomain-bouncy.ai(default), a system domain from GET /v1/domains, or one of your custom domains. Premium system domains need a paid plan; custom domains must be connected and verifiedcustomPath- Path on a custom domain (takes precedence overslugthere)behavior- Redirect behavior, as in Create Link. Free plans are saved asconservativegeoPresetId- ID of a saved geo preset from GET /v1/geo-presets. The link’s geo rule uses the preset’s saved country list. Rows withgeoPresetIdmust also providealternateUrl; unknown preset IDs fail that row’s validationgeoPresetandgeoCountries- A geo rule from a country list (ignored whengeoPresetIdis set)alternateUrl- Redirect destination for visitors matching the geo rule. Required whengeoPresetIdis setlanguagePreset,selectedLanguagesandlanguageUrl- A language rulelinkType: "app"withappLinkConfig- Create an app link instead of a deeplink
Plan limits
- If the batch would take the account past its total link limit, the request fails with
403and nothing is created. - Links count toward the active limit in row order. Once the active limit is reached, the remaining rows are created inactive (the same as a single create at the limit). Activate them later with Toggle Link Status after freeing a slot.
Response
boolean
Whether the batch was created
integer
Number of links created
integer
Number of links created active
integer
Number of links created inactive because the active limit was reached
array
array
Only when the batch includes custom-domain links: one entry per custom-domain row with
domain, path and success. Each custom domain is deployed once for the whole batch, so every row of a domain shares that deployment’s resultcurl -X POST https://api.bouncy.ai/v1/links/bulk \
-H "Authorization: Bearer bcy_live_pk_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"links": [
{ "url": "https://example.com/page1", "slug": "page1" },
{ "url": "https://example.com/page2", "slug": "page2", "domain": "tapmy.social" },
{ "url": "https://example.com/page3", "slug": "page3" }
]
}'
const response = await fetch('https://api.bouncy.ai/v1/links/bulk', {
method: 'POST',
headers: {
'Authorization': 'Bearer bcy_live_pk_YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
links: [
{ url: 'https://example.com/page1', slug: 'page1' },
{ url: 'https://example.com/page2', slug: 'page2', domain: 'tapmy.social' },
{ url: 'https://example.com/page3', slug: 'page3' }
]
})
});
const result = await response.json();
console.log(`Created ${result.totalCreated} links (${result.inactiveCreated} inactive)`);
import requests
response = requests.post(
'https://api.bouncy.ai/v1/links/bulk',
headers={
'Authorization': 'Bearer bcy_live_pk_YOUR_API_KEY',
'Content-Type': 'application/json'
},
json={
'links': [
{'url': 'https://example.com/page1', 'slug': 'page1'},
{'url': 'https://example.com/page2', 'slug': 'page2', 'domain': 'tapmy.social'},
{'url': 'https://example.com/page3', 'slug': 'page3'}
]
}
)
result = response.json()
print(f"Created {result['totalCreated']} links ({result['inactiveCreated']} inactive)")
{
"success": true,
"message": "Successfully created 3 deeplinks",
"totalCreated": 3,
"activeCreated": 2,
"inactiveCreated": 1,
"links": [
{ "id": "page1", "slug": "page1", "domain": "bouncy.ai", "url": "https://bouncy.ai/page1", "isActive": true },
{ "id": "tapmy.social__page2", "slug": "page2", "domain": "tapmy.social", "url": "https://tapmy.social/page2", "isActive": true },
{ "id": "page3", "slug": "page3", "domain": "bouncy.ai", "url": "https://bouncy.ai/page3", "isActive": false }
]
}
{
"error": "Validation failed",
"details": [
"Row 1: The slug \"admin\" is reserved and cannot be used",
"Row 2: Premium domains like tapmy.social are only available on paid plans. Please upgrade to access premium domains.",
"Row 3: Domain shop.example.com is not verified. Add its DNS records and verify it first.",
"Row 4: Destination URL must be a valid HTTP or HTTPS URL"
]
}
{
"error": "Cannot create 3 deeplinks. This would exceed your total limit of 10. You can create 1 more deeplinks."
}