> ## 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.

# Bulk Operations

> Create and delete multiple links at once for large-scale campaigns

## 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

<CodeGroup>
  ```bash cURL theme={null}
  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",
          "title": "Page 1"
        },
        {
          "url": "https://example.com/page2",
          "slug": "page2",
          "title": "Page 2"
        },
        {
          "url": "https://example.com/page3",
          "slug": "page3",
          "title": "Page 3"
        }
      ]
    }'
  ```

  ```javascript JavaScript theme={null}
  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', title: 'Page 1' },
        { url: 'https://example.com/page2', slug: 'page2', title: 'Page 2' },
        { url: 'https://example.com/page3', slug: 'page3', title: 'Page 3' }
      ]
    })
  });

  const result = await response.json();
  console.log(`Created ${result.created.length} links`);
  ```

  ```python Python theme={null}
  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', 'title': 'Page 1'},
              {'url': 'https://example.com/page2', 'slug': 'page2', 'title': 'Page 2'},
              {'url': 'https://example.com/page3', 'slug': 'page3', 'title': 'Page 3'}
          ]
      }
  )

  result = response.json()
  print(f"Created {len(result['created'])} links")
  ```
</CodeGroup>

### Response Format

```json theme={null}
{
  "created": [
    {
      "id": "link_abc123",
      "shortUrl": "https://bouncy.ai/page1",
      "slug": "page1",
      "destination": "https://example.com/page1"
    },
    {
      "id": "link_def456",
      "shortUrl": "https://bouncy.ai/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

<Note>
  Partial success is supported - if some links fail, the successful ones are still created.
</Note>

## Real-World Examples

### Marketing Campaign with UTM Parameters

Generate 50 links for a social media campaign across platforms:

```javascript theme={null}
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: {
    'Authorization': 'Bearer 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:

```javascript theme={null}
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: {
          'Authorization': 'Bearer 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

<CodeGroup>
  ```bash cURL theme={null}
  curl -X DELETE https://api.bouncy.ai/v1/links/bulk \
    -H "Authorization: Bearer bcy_live_pk_YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "linkIds": ["link_abc123", "link_def456", "link_ghi789"]
    }'
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch('https://api.bouncy.ai/v1/links/bulk', {
    method: 'DELETE',
    headers: {
      'Authorization': 'Bearer bcy_live_pk_YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      linkIds: ['link_abc123', 'link_def456', 'link_ghi789']
    })
  });

  const result = await response.json();
  console.log(`Deleted ${result.deleted.length} links`);
  ```

  ```python Python theme={null}
  response = requests.delete(
      'https://api.bouncy.ai/v1/links/bulk',
      headers={
          'Authorization': 'Bearer bcy_live_pk_YOUR_API_KEY',
          'Content-Type': 'application/json'
      },
      json={
          'linkIds': ['link_abc123', 'link_def456', 'link_ghi789']
      }
  )

  result = response.json()
  print(f"Deleted {len(result['deleted'])} links")
  ```
</CodeGroup>

### Response

```json theme={null}
{
  "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:

```javascript theme={null}
// Step 1: Get all links with tag "expired"
const response = await fetch('https://api.bouncy.ai/v1/links?tag=expired&limit=100', {
  headers: { 'Authorization': 'Bearer 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: {
      'Authorization': 'Bearer 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

<AccordionGroup>
  <Accordion title="Batch size limit: 100 links">
    The API accepts a maximum of 100 links per request. For larger operations, split into multiple batches:

    ```javascript theme={null}
    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: {
            'Authorization': 'Bearer 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;
    }
    ```
  </Accordion>

  <Accordion title="Handle partial failures">
    Always check the `failed` array in the response:

    ```javascript theme={null}
    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`);
    ```
  </Accordion>

  <Accordion title="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.
  </Accordion>

  <Accordion title="Add delays between batches">
    When processing multiple batches, add a small delay to avoid overwhelming the API:

    ```javascript theme={null}
    for (const batch of batches) {
      await createBatch(batch);
      await new Promise(resolve => setTimeout(resolve, 1000)); // 1 second delay
    }
    ```
  </Accordion>
</AccordionGroup>

## Error Handling

### Quota Exceeded

If you exceed your plan's link limit, the entire bulk request fails:

```json theme={null}
{
  "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](https://bouncy.ai/pricing).

### Some Links Failed

If individual links fail validation, they appear in the `failed` array:

```json theme={null}
{
  "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

<CardGroup cols={2}>
  <Card title="Create Link" icon="link" href="/api-reference/links/create-link">
    Create a single link with full customization
  </Card>

  <Card title="Get Analytics" icon="chart-line" href="/api-reference/analytics/get-summary">
    Get aggregated analytics across all links
  </Card>

  <Card title="Organize with Groups" icon="folder" href="/api-reference/groups/create-group">
    Create groups to organize bulk-created links
  </Card>

  <Card title="Error Handling" icon="triangle-exclamation" href="/guides/error-handling">
    Handle errors and rate limits
  </Card>
</CardGroup>
