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.

Developer
4 min read
By Laurent Schaffner
Updated March 20, 2025

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
  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')
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}')
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}')
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}')
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)

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}')

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',
                    'leadScore': 85
                }
            ),
            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? 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)}')

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?

Create test mode API keys from your dashboard. They operate on isolated test data separate from production analytics. You can identify test vs production keys by decoding the JWT and checking the environment claim.

Sources

Last reviewed

This article was last reviewed on March 20, 2025.

About the Author

LS

Laurent Schaffner

Founder & Engineer at Linkbreakers

Passionate about building tools that help businesses track and optimize their digital marketing efforts. Laurent founded Linkbreakers to make QR code analytics accessible and actionable for companies of all sizes.