curl -X POST https://api.bouncy.ai/v1/links \
-H "Authorization: Bearer bcy_live_pk_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/summer-sale",
"slug": "summer",
"title": "Summer Sale 2026",
"description": "50% off everything",
"tags": ["marketing", "sale"]
}'
const response = await fetch('https://api.bouncy.ai/v1/links', {
method: 'POST',
headers: {
'Authorization': 'Bearer bcy_live_pk_YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
url: 'https://example.com/summer-sale',
slug: 'summer',
title: 'Summer Sale 2026',
description: '50% off everything',
tags: ['marketing', 'sale']
})
});
const { data: link } = await response.json();
console.log(link.url);
import requests
response = requests.post(
'https://api.bouncy.ai/v1/links',
headers={
'Authorization': 'Bearer bcy_live_pk_YOUR_API_KEY',
'Content-Type': 'application/json'
},
json={
'url': 'https://example.com/summer-sale',
'slug': 'summer',
'title': 'Summer Sale 2026',
'description': '50% off everything',
'tags': ['marketing', 'sale']
}
)
link = response.json()['data']
print(link['url'])
{
"success": true,
"data": {
"id": "summer",
"url": "https://bouncy.ai/summer",
"slug": "summer",
"destination": "https://example.com/summer-sale",
"domain": "bouncy.ai",
"title": "Summer Sale 2026",
"description": "50% off everything",
"tags": ["marketing", "sale"],
"isActive": true,
"createdAt": "2026-02-06T12:00:00Z",
"type": "deeplink",
"groupId": null
}
}
{
"error": "Missing custom slug"
}
{
"error": "Custom slug or domain already taken"
}
{
"error": "The slug \"admin\" is reserved and cannot be used",
"code": "INVALID_SLUG",
"field": "slug"
}
{
"error": "You have reached the maximum number of websites and deeplinks (10) allowed for your growth plan. Please upgrade to create more.",
"code": "TOTAL_LINK_LIMIT_REACHED",
"currentUsed": 10,
"totalLimit": 10,
"plan": "growth"
}
Links
Create Link
Create a new short link with optional customization
POST
/
v1
/
links
curl -X POST https://api.bouncy.ai/v1/links \
-H "Authorization: Bearer bcy_live_pk_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/summer-sale",
"slug": "summer",
"title": "Summer Sale 2026",
"description": "50% off everything",
"tags": ["marketing", "sale"]
}'
const response = await fetch('https://api.bouncy.ai/v1/links', {
method: 'POST',
headers: {
'Authorization': 'Bearer bcy_live_pk_YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
url: 'https://example.com/summer-sale',
slug: 'summer',
title: 'Summer Sale 2026',
description: '50% off everything',
tags: ['marketing', 'sale']
})
});
const { data: link } = await response.json();
console.log(link.url);
import requests
response = requests.post(
'https://api.bouncy.ai/v1/links',
headers={
'Authorization': 'Bearer bcy_live_pk_YOUR_API_KEY',
'Content-Type': 'application/json'
},
json={
'url': 'https://example.com/summer-sale',
'slug': 'summer',
'title': 'Summer Sale 2026',
'description': '50% off everything',
'tags': ['marketing', 'sale']
}
)
link = response.json()['data']
print(link['url'])
{
"success": true,
"data": {
"id": "summer",
"url": "https://bouncy.ai/summer",
"slug": "summer",
"destination": "https://example.com/summer-sale",
"domain": "bouncy.ai",
"title": "Summer Sale 2026",
"description": "50% off everything",
"tags": ["marketing", "sale"],
"isActive": true,
"createdAt": "2026-02-06T12:00:00Z",
"type": "deeplink",
"groupId": null
}
}
{
"error": "Missing custom slug"
}
{
"error": "Custom slug or domain already taken"
}
{
"error": "The slug \"admin\" is reserved and cannot be used",
"code": "INVALID_SLUG",
"field": "slug"
}
{
"error": "You have reached the maximum number of websites and deeplinks (10) allowed for your growth plan. Please upgrade to create more.",
"code": "TOTAL_LINK_LIMIT_REACHED",
"currentUsed": 10,
"totalLimit": 10,
"plan": "growth"
}
Request
Headers
string
required
Must be
application/jsonBody
string
required
The destination URL where the short link should redirect.
Must be an absolute HTTP or HTTPS URL (surrounding spaces are trimmed). Anything else returns
400 with code: "INVALID_DESTINATION_URL".Links on bouncy.ai itself cannot point at a small set of blocked destinations (the same rule as the dashboard, also checked for geoRules and languageRules redirect URLs): the request returns 400 with code: "BLOCKED_BOUNCY_DESTINATION". Use a system domain or your own domain for those.Example: https://example.com/my-pagestring
required
Slug for the short URL. Required on
bouncy.ai and system domains. 3 to 50 characters: letters, numbers, hyphens and underscores (stored lowercase). Reserved words used by Bouncy’s own pages (for example admin, api, login, www) are rejected. Invalid slugs return 400 with code: "INVALID_SLUG".Example: summer-salestring
Title for SEO and social media sharingExample:
Summer Sale 2026string
Description for SEO and social media cardsExample:
Get 50% off all products this summerarray
Array of tags for organizing links (non-string entries are dropped)Example:
["marketing", "summer", "instagram"]string
Domain to use for the short URL:
bouncy.ai, a system domain (e.g., tapmy.social, mybouncy.link) or a custom domain connected and verified in your account. GET /v1/domains lists both. Premium system domains need a paid plan (judged on the link owner’s plan).Example: bouncy.ai
Default: bouncy.aistring
ID of one of the link owner’s groups (GET /v1/groups) to add this link to. An unknown group returns
400 with code: "GROUP_NOT_FOUND".Example: grp_abc123string
Redirect behavior. One of:
conservative (default), aggressive, basic, non-meta, experimental, experimental2, reddit. Free plans are saved as conservative whatever is sent. GET /v1/account/limits lists the behaviors your plan can use.boolean
true creates the link in your team owner’s account (it counts toward the owner’s limits). Requires an active, non-viewer membership of the team; otherwise the request fails with 400, 403 or 404 like the dashboard. Any teamOwnerId in the body is ignored.array
Array of geographic filtering rules. Rules are evaluated in order and the first matching rule wins. Visitors who match no rule are redirected to the main destination
url.Each rule is an object with:countries(array) - ISO 3166-1 alpha-2 codes (e.g.,US,GB) or full country namespresetId(string) - ID of a saved geo preset, as returned by GET /v1/geo-presets. Use this in place ofcountries: the server fills the rule’s countries from the preset’s saved country list when the link is saved. An unknownpresetIdreturns a400errorcities(array) - City names, matched as case-insensitive substrings. Can be combined with eithercountriesorpresetIdredirectUrl(string) - Destination URL for visitors matching this rule. Always required, including when the rule usespresetId
[
{
"countries": ["US", "GB"],
"cities": ["Manchester"],
"redirectUrl": "https://example.com/uk-us-landing"
},
{
"presetId": "a1B2c3D4e5F6g7H8",
"redirectUrl": "https://example.com/preset-landing"
}
]
array
Array of language-based filtering rules
Plan limits
- At the account’s total link limit the request returns
403withcode: "TOTAL_LINK_LIMIT_REACHED",currentUsed,totalLimitandplan. Nothing is created. - At the active link limit the link is still created, but inactive: the response has
isActive: falseandinactiveReason: "active_limit_reached". Activate it later with Toggle Link Status after freeing a slot. - Unlimited plans never hit either limit. GET /v1/account/limits shows the current numbers.
Response
boolean
Whether the operation succeeded
object
The created link object
Show properties
Show properties
string
Unique identifier for the link
string
The complete short URL
string
The slug portion of the short URL
string
The destination URL
string
Domain used for the short URL
string
Link title
string
Link description
array
Array of tags
boolean
Whether the link is active
string
Only present when the link was created inactive:
active_limit_reachedstring
deeplink, or applink for app linksstring
The group the link was added to, or
nullstring
ISO 8601 timestamp of creation
curl -X POST https://api.bouncy.ai/v1/links \
-H "Authorization: Bearer bcy_live_pk_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/summer-sale",
"slug": "summer",
"title": "Summer Sale 2026",
"description": "50% off everything",
"tags": ["marketing", "sale"]
}'
const response = await fetch('https://api.bouncy.ai/v1/links', {
method: 'POST',
headers: {
'Authorization': 'Bearer bcy_live_pk_YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
url: 'https://example.com/summer-sale',
slug: 'summer',
title: 'Summer Sale 2026',
description: '50% off everything',
tags: ['marketing', 'sale']
})
});
const { data: link } = await response.json();
console.log(link.url);
import requests
response = requests.post(
'https://api.bouncy.ai/v1/links',
headers={
'Authorization': 'Bearer bcy_live_pk_YOUR_API_KEY',
'Content-Type': 'application/json'
},
json={
'url': 'https://example.com/summer-sale',
'slug': 'summer',
'title': 'Summer Sale 2026',
'description': '50% off everything',
'tags': ['marketing', 'sale']
}
)
link = response.json()['data']
print(link['url'])
{
"success": true,
"data": {
"id": "summer",
"url": "https://bouncy.ai/summer",
"slug": "summer",
"destination": "https://example.com/summer-sale",
"domain": "bouncy.ai",
"title": "Summer Sale 2026",
"description": "50% off everything",
"tags": ["marketing", "sale"],
"isActive": true,
"createdAt": "2026-02-06T12:00:00Z",
"type": "deeplink",
"groupId": null
}
}
{
"error": "Missing custom slug"
}
{
"error": "Custom slug or domain already taken"
}
{
"error": "The slug \"admin\" is reserved and cannot be used",
"code": "INVALID_SLUG",
"field": "slug"
}
{
"error": "You have reached the maximum number of websites and deeplinks (10) allowed for your growth plan. Please upgrade to create more.",
"code": "TOTAL_LINK_LIMIT_REACHED",
"currentUsed": 10,
"totalLimit": 10,
"plan": "growth"
}