---
title: "Linkbreakers Python SDK: Complete Integration Guide"
description: "Learn how to integrate the Linkbreakers Python SDK in your backend application for programmatic link management, visitor tracking, QR code generation, and analytics. Includes installation, authentication, and real code examples for Django, Flask, and FastAPI."
canonical: "https://linkbreakers.com/help/article/python-sdk-quickstart"
last-updated: 2026-10-27
---

# Linkbreakers Python SDK: Complete Integration Guide

> Learn how to integrate the Linkbreakers Python SDK in your backend application for programmatic link management, visitor tracking, QR code generation, and analytics. Includes installation, authentication, and real code examples for Django, Flask, and FastAPI.

## Short answer

The Linkbreakers Python SDK enables programmatic link management, visitor identification, QR code generation, and analytics access from your Python backend applications. Install it with `pip install linkbreakers`, authenticate with a secret API key, and start creating trackable links for your campaigns, products, or events.

## Installation

Install the SDK using pip:

```bash
pip install linkbreakers
```

For Poetry users:

```bash
poetry add linkbreakers
```

For pipenv:

```bash
pipenv install linkbreakers
```

## Understanding API keys for Python

The Python SDK is designed for **backend/server-side use only** and requires a **secret API key** with full workspace access.

### Secret keys

**Backend-only.** These JWT tokens grant full API access and must never be exposed in public repositories or client-side code.

**What they allow:**
- Create, update, and delete links
- Generate and customize QR codes
- Identify and track visitors
- Access analytics and metrics
- Manage workspace resources
- Full API access

**Where to use:**
- Django/Flask/FastAPI applications
- Background jobs and cron tasks
- CI/CD pipelines
- Serverless functions (AWS Lambda, Google Cloud Functions)
- Data processing scripts
- Internal tools and dashboards

**Security note:** Python applications typically run on servers, making them perfect for secret key usage. Never log keys, commit them to git, or expose them in error messages.

## Creating a secret API key

Create your API key from the dashboard:

1. Log in to [app.linkbreakers.com](https://app.linkbreakers.com)
2. Navigate to **Dashboard → API Tokens**
3. Click **Create API Token**
4. Select **Secret Key** (full API access)
5. Give it a descriptive name (e.g., "Production Backend" or "Analytics Pipeline")
6. Copy the generated JWT token immediately

**Important:** You won't see the key again after creation. Store it in environment variables or a secret management system (AWS Secrets Manager, HashiCorp Vault, etc.).

## Quick start

Initialize the client and create your first shortened link:

```python
from linkbreakers import Configuration, ApiClient, LinksApi

# Configure API client
configuration = Configuration(
    access_token='eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...',  # Your JWT token
    host='https://api.linkbreakers.com'
)

with ApiClient(configuration) as api_client:
    links_api = LinksApi(api_client)

    # Create a shortened link
    response = links_api.links_service_create({
        'destination': 'https://example.com/product',
        'name': 'Product Launch - Spring 2025',
        'tags': ['marketing', 'product-launch']
    })

    print(f'Short URL: {response.link.shortlink}')
    print(f'Link ID: {response.link.id}')
    print(f'QR Code: {response.link.qrcode_signed_url}')
```

**Context manager:** The `with ApiClient(configuration) as api_client` pattern ensures proper connection handling and cleanup. Always use this pattern in production code.

## Environment variables (best practice)

Never hardcode API keys. Use environment variables:

```python
import os
from linkbreakers import Configuration, ApiClient, LinksApi

# Read from environment variable
configuration = Configuration(
    access_token=os.getenv('LINKBREAKERS_SECRET_KEY'),
    host='https://api.linkbreakers.com'
)

with ApiClient(configuration) as api_client:
    links_api = LinksApi(api_client)
    # ... use the API
```

**Set your environment variable:**

```bash
# .env file (use python-dotenv to load)
LINKBREAKERS_SECRET_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ3b3Jrc3BhY2VfaWQiOiIxMjM0IiwidHlwZSI6InNlY3JldCJ9...

# Or export directly in shell
export LINKBREAKERS_SECRET_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
```

**Loading .env files with python-dotenv:**

```python
from dotenv import load_dotenv
import os

load_dotenv()  # Loads variables from .env file

api_key = os.getenv('LINKBREAKERS_SECRET_KEY')
```

## Creating and managing links

### Basic link creation

```python
from linkbreakers import Configuration, ApiClient, LinksApi, CreateLinkRequest

configuration = Configuration(
    access_token=os.getenv('LINKBREAKERS_SECRET_KEY'),
    host='https://api.linkbreakers.com'
)

with ApiClient(configuration) as api_client:
    links_api = LinksApi(api_client)

    # Create a basic link
    response = links_api.links_service_create(
        create_link_request=CreateLinkRequest(
            destination='https://example.com/summer-sale',
            name='Summer Sale 2025',
            tags=['campaign', 'summer', 'email']
        )
    )

    print(f'Created: {response.link.shortlink}')
```

### Advanced link options

```python
from linkbreakers import Configuration, ApiClient, LinksApi, CreateLinkRequest

configuration = Configuration(
    access_token=os.getenv('LINKBREAKERS_SECRET_KEY'),
    host='https://api.linkbreakers.com'
)

with ApiClient(configuration) as api_client:
    links_api = LinksApi(api_client)

    # Create link with custom shortlink
    custom_link = links_api.links_service_create(
        create_link_request=CreateLinkRequest(
            destination='https://example.com/docs',
            shortlink='docs',  # Creates lbr.ai/docs
            name='Documentation Portal',
            fallback_destination='https://example.com/404',
            tags=['internal', 'docs']
        )
    )

    # Create link with metadata for tracking
    tracked_link = links_api.links_service_create(
        create_link_request=CreateLinkRequest(
            destination='https://example.com/product/123',
            name='Product 123 - Email Campaign',
            metadata={
                'product_id': '123',
                'campaign_id': 'spring-2025',
                'utm_source': 'email',
                'utm_medium': 'newsletter',
                'utm_campaign': 'product-launch'
            },
            tags=['product', 'email']
        )
    )

    # Create link with QR code (wait for generation)
    qr_link = links_api.links_service_create(
        create_link_request=CreateLinkRequest(
            destination='https://example.com/event-registration',
            name='Conference 2025 Registration',
            wait_for_qrcode=True,  # Blocks until QR is generated
            tags=['event', 'conference', 'qr-code']
        )
    )

    print(f'Download QR code: {qr_link.link.qrcode_signed_url}')
```

### Listing and filtering links

```python
from linkbreakers import Configuration, ApiClient, LinksApi

configuration = Configuration(
    access_token=os.getenv('LINKBREAKERS_SECRET_KEY'),
    host='https://api.linkbreakers.com'
)

with ApiClient(configuration) as api_client:
    links_api = LinksApi(api_client)

    # List links with filtering
    list_response = links_api.links_service_list(
        page_size=50,
        tags=['marketing', 'email'],
        search='campaign',
        sort_by='LINK_SORT_FIELD_UPDATED_AT',
        sort_direction='SORT_DIRECTION_DESC'
    )

    for link in list_response.links:
        print(f'{link.name}: {link.shortlink}')
        print(f'  Tags: {", ".join(link.tags or [])}')
        print(f'  Created: {link.created_at}')
```

### Updating and deleting links

```python
from linkbreakers import Configuration, ApiClient, LinksApi

configuration = Configuration(
    access_token=os.getenv('LINKBREAKERS_SECRET_KEY'),
    host='https://api.linkbreakers.com'
)

with ApiClient(configuration) as api_client:
    links_api = LinksApi(api_client)

    # Get a specific link
    link = links_api.links_service_get(
        id='your-link-uuid',
        include=['tags', 'qrcodeSignedUrl']
    )

    # Update link
    links_api.links_service_update(
        id=link.link.id,
        update_link_request={
            'name': 'Updated Campaign Name',
            'tags': ['marketing', 'q2-2025', 'updated']
        }
    )

    # Delete link
    links_api.links_service_delete(id=link.link.id)
```

## Bulk link creation

Create hundreds of links efficiently in a single API call:

```python
from linkbreakers import (
    Configuration,
    ApiClient,
    LinksApi,
    CreateLinkRequest,
    CreateBulkLinksRequest
)

configuration = Configuration(
    access_token=os.getenv('LINKBREAKERS_SECRET_KEY'),
    host='https://api.linkbreakers.com'
)

with ApiClient(configuration) as api_client:
    links_api = LinksApi(api_client)

    # Prepare bulk links (e.g., from a product catalog)
    products = [
        {'id': '001', 'name': 'Widget A', 'url': 'https://example.com/products/001'},
        {'id': '002', 'name': 'Widget B', 'url': 'https://example.com/products/002'},
        {'id': '003', 'name': 'Widget C', 'url': 'https://example.com/products/003'},
    ]

    links_to_create = [
        CreateLinkRequest(
            destination=p['url'],
            name=f"Product: {p['name']}",
            tags=['product', 'catalog'],
            metadata={'product_id': p['id'], 'sku': f"SKU-{p['id']}"}
        )
        for p in products
    ]

    # Create all links in one request
    response = links_api.links_service_create_bulk(
        create_bulk_links_request=CreateBulkLinksRequest(
            links=links_to_create
        )
    )

    print(f'Created {len(response.links)} links')
    for link in response.links:
        print(f'  {link.name}: {link.shortlink}')
```

A bulk request takes up to 250 links and is transactional: if one link is invalid, none are created.

For a complete, runnable version that reads a CSV, saves one SVG QR code per row and exports scan counts back to a CSV, see the [bulk dynamic QR codes from a CSV example](https://github.com/linkbreakers-com/examples/tree/main/bulk-dynamic-qr-codes-from-csv-python) on GitHub.

**When to use bulk creation:**
- Importing product catalogs
- Generating links from CSV/database
- Campaign setup with many URLs
- Automated link generation pipelines

## Visitor identification and tracking

Track and identify visitors using their LBID (Linkbreakers ID) from click/scan events:

```python
from linkbreakers import (
    Configuration,
    ApiClient,
    VisitorsApi,
    IdentifyRequest,
    VisitorInput
)

configuration = Configuration(
    access_token=os.getenv('LINKBREAKERS_SECRET_KEY'),
    host='https://api.linkbreakers.com'
)

with ApiClient(configuration) as api_client:
    visitors_api = VisitorsApi(api_client)

    # Identify a visitor using their LBID
    # LBID comes from ?lbid= parameter when users click your links
    response = visitors_api.visitors_service_identify(
        identify_request=IdentifyRequest(
            lbid='visitor-lbid-from-url-parameter',
            visitor=VisitorInput(
                data={
                    # System fields (prefixed with "$")
                    '$email': 'john.doe@example.com',
                    '$phone': '+14155551234',
                    '$firstName': 'John',
                    '$lastName': 'Doe',

                    # Custom attributes (no "$" prefix)
                    'company': 'Acme Corporation',
                    'jobTitle': 'Product Manager',
                    'plan': 'enterprise',
                    'signupDate': '2024-01-15',
                    'industry': 'SaaS',
                    'employees': 250
                }
            ),
            set_once=False  # True = only update empty fields
        )
    )

    print(f'New profile created: {response.created}')
    print(f'Visitor ID: {response.visitor.id}')
    print(f'Email: {response.visitor.email}')
```

**Understanding LBID:**

When visitors click your Linkbreakers links with **conversion tracking enabled**, a `?lbid=...` parameter is added to the destination URL. This LBID connects the visitor to the specific link click, enabling attribution and analytics.

Extract LBID from incoming requests and pass it to the identification API to build visitor profiles. Learn more in our [What is LBID?](/help/article/what-is-the-linkbreakers-id-lbid) guide.

### Working with visitor data

```python
from linkbreakers import Configuration, ApiClient, VisitorsApi

configuration = Configuration(
    access_token=os.getenv('LINKBREAKERS_SECRET_KEY'),
    host='https://api.linkbreakers.com'
)

with ApiClient(configuration) as api_client:
    visitors_api = VisitorsApi(api_client)

    # Get visitor details
    visitor = visitors_api.visitors_service_get(
        id='visitor-uuid',
        include=['devices', 'events', 'links']
    )

    print(f'Visitor: {visitor.email}')
    print(f'Devices: {len(visitor.devices or [])}')
    print(f'Events: {len(visitor.events or [])}')

    # List visitors with filtering
    visitors_list = visitors_api.visitors_service_list(
        page_size=100,
        email='user@example.com',  # Filter by email
        link_id='link-uuid',       # Filter by link
        search='Acme Corp'         # Search in attributes
    )

    # Update visitor attributes
    visitors_api.visitors_service_update(
        id='visitor-uuid',
        visitors_service_update_body={
            'visitor': {
                'data': {
                    '$email': 'updated@example.com',
                    'plan': 'enterprise',
                    'lastActivity': '2025-03-20'
                }
            }
        }
    )
```

## Accessing analytics and metrics

Retrieve event data and workspace metrics:

```python
from linkbreakers import Configuration, ApiClient, EventsApi, MetricsApi
from datetime import datetime, timedelta

configuration = Configuration(
    access_token=os.getenv('LINKBREAKERS_SECRET_KEY'),
    host='https://api.linkbreakers.com'
)

with ApiClient(configuration) as api_client:
    events_api = EventsApi(api_client)
    metrics_api = MetricsApi(api_client)

    # Get events for a specific link (last 30 days)
    end_date = datetime.now()
    start_date = end_date - timedelta(days=30)

    events_response = events_api.events_service_list(
        link_id='your-link-uuid',
        start_date=start_date.isoformat(),
        end_date=end_date.isoformat(),
        page_size=1000,
        include=['visitor', 'device', 'link']
    )

    print(f'Total events: {len(events_response.events)}')
    for event in events_response.events[:10]:
        print(f'  {event.action} - {event.created_at}')

    # Get workspace metrics
    metrics = metrics_api.metrics_service_get_workspace_metrics()
    print(f'\nWorkspace Stats:')
    print(f'  Total links: {metrics.total_links}')
    print(f'  Total clicks: {metrics.total_clicks}')
    print(f'  Total visitors: {metrics.total_visitors}')
```

## Framework integration

### Django

**Settings configuration:**

```python
# settings.py
import os
from dotenv import load_dotenv

load_dotenv()

LINKBREAKERS_SECRET_KEY = os.getenv('LINKBREAKERS_SECRET_KEY')
```

**View example:**

```python
# views.py
from django.http import JsonResponse
from django.conf import settings
from linkbreakers import Configuration, ApiClient, LinksApi

def create_short_link(request):
    configuration = Configuration(
        access_token=settings.LINKBREAKERS_SECRET_KEY,
        host='https://api.linkbreakers.com'
    )

    with ApiClient(configuration) as api_client:
        links_api = LinksApi(api_client)

        response = links_api.links_service_create({
            'destination': request.POST.get('url'),
            'name': request.POST.get('name'),
            'tags': ['django', 'webapp']
        })

        return JsonResponse({
            'success': True,
            'shortlink': response.link.shortlink
        })
```

**Model integration:**

```python
# models.py
from django.db import models
from linkbreakers import Configuration, ApiClient, LinksApi
from django.conf import settings

class Campaign(models.Model):
    name = models.CharField(max_length=200)
    destination_url = models.URLField()
    short_link = models.URLField(blank=True)
    link_id = models.UUIDField(null=True, blank=True)

    def create_short_link(self):
        configuration = Configuration(
            access_token=settings.LINKBREAKERS_SECRET_KEY,
            host='https://api.linkbreakers.com'
        )

        with ApiClient(configuration) as api_client:
            links_api = LinksApi(api_client)

            response = links_api.links_service_create({
                'destination': self.destination_url,
                'name': self.name,
                'tags': ['campaign'],
                'metadata': {'django_model_id': str(self.id)}
            })

            self.short_link = response.link.shortlink
            self.link_id = response.link.id
            self.save()
```

### Flask

```python
from flask import Flask, request, jsonify
from linkbreakers import Configuration, ApiClient, LinksApi
import os

app = Flask(__name__)

# Initialize configuration once
configuration = Configuration(
    access_token=os.getenv('LINKBREAKERS_SECRET_KEY'),
    host='https://api.linkbreakers.com'
)

@app.route('/api/create-link', methods=['POST'])
def create_link():
    with ApiClient(configuration) as api_client:
        links_api = LinksApi(api_client)

        data = request.get_json()
        response = links_api.links_service_create({
            'destination': data['destination'],
            'name': data.get('name', 'Untitled Link'),
            'tags': data.get('tags', [])
        })

        return jsonify({
            'success': True,
            'shortlink': response.link.shortlink,
            'qr_code': response.link.qrcode_signed_url
        })

@app.route('/api/links', methods=['GET'])
def list_links():
    with ApiClient(configuration) as api_client:
        links_api = LinksApi(api_client)

        response = links_api.links_service_list(
            page_size=50,
            tags=request.args.getlist('tags')
        )

        return jsonify({
            'links': [
                {
                    'id': link.id,
                    'name': link.name,
                    'shortlink': link.shortlink,
                    'destination': link.destination
                }
                for link in response.links
            ]
        })

if __name__ == '__main__':
    app.run(debug=True)
```

### FastAPI

```python
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel, HttpUrl
from linkbreakers import Configuration, ApiClient, LinksApi
import os

app = FastAPI()

# Initialize configuration
configuration = Configuration(
    access_token=os.getenv('LINKBREAKERS_SECRET_KEY'),
    host='https://api.linkbreakers.com'
)

class CreateLinkRequest(BaseModel):
    destination: HttpUrl
    name: str
    tags: list[str] = []

class LinkResponse(BaseModel):
    id: str
    shortlink: str
    qr_code: str | None

@app.post("/api/create-link", response_model=LinkResponse)
async def create_link(request: CreateLinkRequest):
    with ApiClient(configuration) as api_client:
        links_api = LinksApi(api_client)

        response = links_api.links_service_create({
            'destination': str(request.destination),
            'name': request.name,
            'tags': request.tags
        })

        return LinkResponse(
            id=response.link.id,
            shortlink=response.link.shortlink,
            qr_code=response.link.qrcode_signed_url
        )

@app.get("/api/links")
async def list_links(tag: str | None = None, page_size: int = 50):
    with ApiClient(configuration) as api_client:
        links_api = LinksApi(api_client)

        response = links_api.links_service_list(
            page_size=page_size,
            tags=[tag] if tag else None
        )

        return {
            'links': [
                {
                    'id': link.id,
                    'name': link.name,
                    'shortlink': link.shortlink
                }
                for link in response.links
            ]
        }
```

## Error handling

Implement proper error handling for production:

```python
from linkbreakers import Configuration, ApiClient, LinksApi, ApiException

configuration = Configuration(
    access_token=os.getenv('LINKBREAKERS_SECRET_KEY'),
    host='https://api.linkbreakers.com'
)

try:
    with ApiClient(configuration) as api_client:
        links_api = LinksApi(api_client)

        response = links_api.links_service_create({
            'destination': 'https://example.com/page',
            'name': 'My Link'
        })

        print(f'Success: {response.link.shortlink}')

except ApiException as e:
    print(f'API Error: {e.status} - {e.reason}')
    print(f'Response body: {e.body}')

except Exception as e:
    print(f'Unexpected error: {str(e)}')
```

To let an AI agent drive the Python SDK, or to use the MCP server instead, see [How Linkbreakers works with AI agents](/help/article/linkbreakers-for-ai-agents).

## Frequently asked questions

**Can I use the Python SDK in Django or Flask applications?**

Yes! The SDK is framework-agnostic and works seamlessly with Django, Flask, FastAPI, Pyramid, and any Python web framework.

**How do I handle rate limits?**

The SDK will raise `ApiException` if you exceed rate limits. Implement exponential backoff retry logic for production applications.

**Does the SDK support async/await?**

The current version uses synchronous HTTP calls. For async frameworks like FastAPI, run SDK calls in thread pools using `asyncio.to_thread()` or use background tasks.

**How do I get the LBID for visitor identification?**

The LBID appears as a `?lbid=` query parameter when visitors click your links with conversion tracking enabled. Extract it from request parameters and pass it to `visitors_service_identify()`.

**Can I create bulk links efficiently?**

Yes, use `links_service_create_bulk()` to create up to 1000 links in a single API call, which is much more efficient than individual requests.

**What Python versions are supported?**

The SDK supports Python 3.7+ with full type hints for modern IDE autocompletion and type checking.

**How do I test without affecting production data?**

There is no separate test mode. Use a [separate workspace](/help/article/work-across-multiple-workspaces) for development and CI, with its own API token, so tests never touch your live links or analytics. Tag test links so they are easy to find and delete.

## Sources

- [Linkbreakers Python SDK GitHub Repository](https://github.com/linkbreakers-com/linkbreakers-python)
- [Linkbreakers Python SDK on PyPI](https://pypi.org/project/linkbreakers/)
- [What is LBID?](https://linkbreakers.com/help/article/what-is-the-linkbreakers-id-lbid)
- [Linkbreakers API Documentation](https://linkbreakers.com/help/article/how-to-use-the-linkbreakers-api)

## Last reviewed

This article was last reviewed on March 20, 2025.
