Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.bouncy.ai/llms.txt

Use this file to discover all available pages before exploring further.

Overview

The Bouncy.ai API provides detailed analytics for individual links, bio websites, and aggregate data across your entire account. Track:
  • Views and clicks - Total views, tracked clicks, and time-series trends
  • Website button clicks - Per-button click totals and daily click counts for bio pages
  • Geographic data - Country-level location
  • Device information - Mobile vs desktop and platform breakdowns
  • Referrer sources - Where your traffic comes from
  • Time series data - Clicks over time with hourly/daily granularity
  • Adult confirmations - Confirmation count and rate for adult-gated links
Retrieve detailed analytics for a specific link or bio website. For websites, use the website document ID, custom slug, or custom domain:
curl https://api.bouncy.ai/v1/analytics/links/link_abc123 \
  -H "Authorization: Bearer bcy_live_pk_YOUR_API_KEY"

Response

{
  "id": "my-bio-page",
  "identifier": "my-bio-page",
  "type": "Website",
  "resolvedBy": "customSlug",
  "totalViews": 190,
  "dailyViews": [
    {
      "date": "2026-01-15",
      "views": 74,
      "clicks": 32,
      "adultClicks": 0
    }
  ],
  "deviceStats": {
    "mobile": 176,
    "desktop": 14
  },
  "countryStats": [
    { "name": "United States", "views": 112 },
    { "name": "United Kingdom", "views": 49 }
  ],
  "topCountry": "United States",
  "topCountryViews": 112,
  "lastViewed": "2026-01-31T19:22:10.000Z",
  "platformStats": {
    "ios": 104,
    "android": 72,
    "windows": 14
  },
  "referrerStats": [
    { "domain": "instagram.com", "views": 89 },
    { "domain": "direct", "views": 54 }
  ],
  "totalClicks": 88,
  "clicksByLink": [
    {
      "id": "shop_0_lx8abc",
      "count": 88,
      "totalClicks": 88,
      "title": "Shop Now",
      "url": "https://example.com/shop",
      "type": "standard",
      "dailyClicks": [
        { "date": "2026-01-15", "clicks": 32 },
        { "date": "2026-01-16", "clicks": 56 }
      ]
    }
  ],
  "adultConfirmation": null
}

Website Button Click Analytics

Bio website button clicks are included in the same endpoint under clicksByLink. Each item represents one tracked button or social link and includes:
  • id - Stable button/link ID
  • title - Button title shown on the page
  • url - Destination URL
  • count and totalClicks - Total clicks in the selected range
  • dailyClicks - Per-day click counts for that button
GET /v1/analytics/links/my-bio-page?timeframe=last_30_days
const response = await fetch(
  'https://api.bouncy.ai/v1/analytics/links/my-bio-page?timeframe=last_30_days',
  {
    headers: { 'Authorization': 'Bearer bcy_live_pk_YOUR_API_KEY' }
  }
);

const analytics = await response.json();

const buttons = analytics.clicksByLink.map(button => ({
  id: button.id,
  title: button.title,
  url: button.url,
  totalClicks: button.totalClicks,
  dailyClicks: button.dailyClicks
}));

Filter Analytics by Date Range

Add query parameters to filter by date:
GET /v1/analytics/links/link_abc123?from=2026-01-01&to=2026-01-31
curl "https://api.bouncy.ai/v1/analytics/links/link_abc123?from=2026-01-01&to=2026-01-31" \
  -H "Authorization: Bearer bcy_live_pk_YOUR_API_KEY"

Get Summary Analytics

Get aggregated analytics across all your links:
curl https://api.bouncy.ai/v1/analytics/summary \
  -H "Authorization: Bearer bcy_live_pk_YOUR_API_KEY"

Response

{
  "totalLinks": 245,
  "totalClicks": 45678,
  "uniqueVisitors": 32456,
  "averageClicksPerLink": 186,
  "topLinks": [
    {
      "linkId": "link_abc123",
      "shortUrl": "https://bouncy.ai/summer",
      "clicks": 2345
    },
    {
      "linkId": "link_def456",
      "shortUrl": "https://bouncy.ai/promo",
      "clicks": 1987
    }
  ],
  "topCountries": [
    { "country": "US", "clicks": 15678 },
    { "country": "GB", "clicks": 8765 },
    { "country": "CA", "clicks": 5432 }
  ],
  "clicksOverTime": [
    { "date": "2026-02-01", "clicks": 234 },
    { "date": "2026-02-02", "clicks": 345 },
    { "date": "2026-02-03", "clicks": 456 }
  ]
}

Filter Summary by Tags

Get analytics for links with a specific tag:
GET /v1/analytics/summary?tag=summer2026
const response = await fetch(
  'https://api.bouncy.ai/v1/analytics/summary?tag=summer2026',
  {
    headers: { 'Authorization': 'Bearer bcy_live_pk_YOUR_API_KEY' }
  }
);

const campaignAnalytics = await response.json();
console.log(`Campaign clicks: ${campaignAnalytics.totalClicks}`);
This is perfect for tracking campaign performance!

Real-World Use Cases

Campaign Performance Dashboard

Build a custom dashboard showing performance across campaigns:
async function getCampaignStats(campaignTag) {
  const response = await fetch(
    `https://api.bouncy.ai/v1/analytics/summary?tag=${campaignTag}`,
    {
      headers: { 'Authorization': 'Bearer bcy_live_pk_YOUR_API_KEY' }
    }
  );

  const stats = await response.json();

  return {
    campaign: campaignTag,
    totalClicks: stats.totalClicks,
    uniqueVisitors: stats.uniqueVisitors,
    topLink: stats.topLinks[0],
    topCountry: stats.topCountries[0]
  };
}

const campaigns = ['summer2026', 'winter2026', 'blackfriday'];
const results = await Promise.all(
  campaigns.map(tag => getCampaignStats(tag))
);

console.table(results);

Automated Reporting

Send weekly email reports with link performance:
import nodemailer from 'nodemailer';

async function sendWeeklyReport() {
  // Get last 7 days of data
  const endDate = new Date().toISOString().split('T')[0];
  const startDate = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000)
    .toISOString()
    .split('T')[0];

  const response = await fetch(
    `https://api.bouncy.ai/v1/analytics/summary?startDate=${startDate}&endDate=${endDate}`,
    {
      headers: { 'Authorization': 'Bearer bcy_live_pk_YOUR_API_KEY' }
    }
  );

  const stats = await response.json();

  const emailBody = `
    Weekly Link Report (${startDate} to ${endDate})

    Total Clicks: ${stats.totalClicks}
    Unique Visitors: ${stats.uniqueVisitors}

    Top Performing Links:
    ${stats.topLinks.map(link => `  - ${link.shortUrl}: ${link.clicks} clicks`).join('\n')}

    Top Countries:
    ${stats.topCountries.map(c => `  - ${c.country}: ${c.clicks} clicks`).join('\n')}
  `;

  // Send email (configure your SMTP settings)
  const transporter = nodemailer.createTransport({...});
  await transporter.sendMail({
    to: 'team@example.com',
    subject: 'Weekly Bouncy.ai Link Report',
    text: emailBody
  });
}

// Run weekly
setInterval(sendWeeklyReport, 7 * 24 * 60 * 60 * 1000);

A/B Testing

Compare performance of different link variations:
async function compareLinks(linkIds) {
  const results = await Promise.all(
    linkIds.map(async (linkId) => {
      const response = await fetch(
        `https://api.bouncy.ai/v1/analytics/links/${linkId}`,
        {
          headers: { 'Authorization': 'Bearer bcy_live_pk_YOUR_API_KEY' }
        }
      );
      return response.json();
    })
  );

  const comparison = results.map((analytics, index) => ({
    linkId: linkIds[index],
    views: analytics.totalViews,
    clicks: analytics.totalClicks,
    clickRate: analytics.totalViews > 0
      ? (analytics.totalClicks / analytics.totalViews * 100).toFixed(2) + '%'
      : '0.00%',
    adultConfirmations: analytics.adultConfirmation?.clicks ?? 0,
    adultConfirmationRate: analytics.adultConfirmation
      ? analytics.adultConfirmation.rate + '%'
      : 'N/A'
  }));

  console.table(comparison);

  // Determine winner
  const winner = comparison.reduce((prev, current) =>
    current.clicks > prev.clicks ? current : prev
  );

  console.log(`Winner: ${winner.linkId} with ${winner.clicks} clicks`);
  return winner;
}

const testLinks = ['link_abc123', 'link_def456', 'link_ghi789'];
const winner = await compareLinks(testLinks);

Analytics Best Practices

Analytics don’t change instantly - cache results for a few minutes:
const cache = new Map();
const CACHE_TTL = 5 * 60 * 1000; // 5 minutes

async function getCachedAnalytics(linkId) {
  const cached = cache.get(linkId);

  if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
    return cached.data;
  }

  const response = await fetch(
    `https://api.bouncy.ai/v1/analytics/links/${linkId}`,
    {
      headers: { 'Authorization': 'Bearer bcy_live_pk_YOUR_API_KEY' }
    }
  );

  const data = await response.json();
  cache.set(linkId, { data, timestamp: Date.now() });

  return data;
}
When querying large date ranges, the API processes more data. For better performance, query smaller date ranges:
// ❌ Slow: Query entire year
const yearAnalytics = await fetch(
  'https://api.bouncy.ai/v1/analytics/summary?startDate=2026-01-01&endDate=2026-12-31'
);

// ✅ Fast: Query last 30 days
const monthAnalytics = await fetch(
  'https://api.bouncy.ai/v1/analytics/summary?startDate=2026-01-07&endDate=2026-02-06'
);
Always tag your links by campaign so you can filter analytics later:
// Create link with campaign tags
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/sale',
    tags: ['summer2026', 'instagram', 'story']
  })
});

// Later: Get campaign analytics
const analytics = await fetch(
  'https://api.bouncy.ai/v1/analytics/summary?tag=summer2026'
);

Next Steps

Create Links

Create links to start tracking analytics

Organize with Tags

Use tags to group links by campaign

API Reference

Full analytics endpoint documentation

Webhooks

Get notified when links reach milestones (coming soon)