Programmatic QR code generation: API vs AI agents

Compare three approaches to programmatic QR code generation — REST API with SDKs, CLI automation, and AI agents via MCP. Understand when to use each method and how Linkbreakers supports all three.

Developer
11 min read
By Laurent Schaffner
Updated June 6, 2026

Short answer

There are three approaches to programmatic QR code generation: REST API with SDKs for production applications, CLI scripting for DevOps and automation pipelines, and AI agents via MCP for conversational and ad-hoc workflows. Linkbreakers is the only QR code platform that supports all three through a unified backend — the same workspace data, the same authentication system, and the same set of operations accessible from TypeScript, Python, Go, Java, Rust, CLI, or natural language through the Model Context Protocol.

Quick summary

  • REST API + SDKs — Best for production applications, CI/CD integration, and code-level control. Available in TypeScript, Python, Go, Java, and Rust.
  • CLI scripting — Best for DevOps workflows, shell scripts, cron jobs, and terminal-based automation. Outputs human-readable tables or machine-readable JSON.
  • MCP AI agents — Best for ad-hoc campaign setup, one-time bulk operations, conversational analytics, and non-technical users who need programmatic access.
  • All three approaches connect to the same Linkbreakers API and operate on the same workspace data
  • No feature is exclusive to one approach — links, workflows, QR designs, analytics, and domains are available across all three
  • You can mix approaches freely: create a campaign via MCP, monitor it via CLI, and integrate scan events via SDK

Three approaches compared

Approach 1: REST API with SDKs

The REST API is the foundation of programmatic access to Linkbreakers. Every other approach — CLI and MCP — ultimately calls the same API endpoints. The SDKs wrap these endpoints in language-native interfaces with type safety, error handling, and authentication management.

How it works:

Install the SDK for your language, configure authentication with a secret key, and call methods that map to API endpoints. Responses are typed objects you can use directly in your application logic.

TypeScript example — creating a tracked link with QR code:

TypeScript
import { Configuration, LinksApi } from 'linkbreakers';

const config = new Configuration({
  accessToken: process.env.LINKBREAKERS_SECRET_KEY,
  basePath: 'https://api.linkbreakers.com',
});

const linksApi = new LinksApi(config);

const response = await linksApi.linksServiceCreate({
  createLinkRequest: {
    destination: 'https://shop.example.com/product-42',
    name: 'Product 42 Launch',
    slug: 'product-42',
    tags: ['product-launch', 'q3-2026'],
    waitForQrcode: true,
  },
});

console.log('Short URL:', response.link.shortlink);
console.log('QR code:', response.link.qrcodeSignedUrl);

Python example — bulk link creation from a CSV:

Python
import csv
import os
from linkbreakers import Configuration, LinksApi

config = Configuration(
    access_token=os.environ['LINKBREAKERS_SECRET_KEY'],
    host='https://api.linkbreakers.com',
)

links_api = LinksApi(config)

with open('products.csv') as f:
    for row in csv.DictReader(f):
        response = links_api.links_service_create(
            create_link_request={
                'destination': row['url'],
                'name': row['product_name'],
                'tags': ['product-catalog', row['category']],
            }
        )
        print(f"{row['product_name']}: {response.link.shortlink}")

Go example — high-throughput link generation:

Go
package main

import (
    "context"
    "fmt"
    "os"
    linkbreakers "github.com/linkbreakers-com/linkbreakers-go"
)

func main() {
    config := linkbreakers.NewConfiguration()
    config.AddDefaultHeader("Authorization", "Bearer "+os.Getenv("LINKBREAKERS_SECRET_KEY"))
    config.Servers = linkbreakers.ServerConfigurations{
        {URL: "https://api.linkbreakers.com"},
    }

    client := linkbreakers.NewAPIClient(config)
    ctx := context.Background()

    products := []string{"widget-a", "widget-b", "widget-c"}
    for _, product := range products {
        request := linkbreakers.NewCreateLinkRequest(
            fmt.Sprintf("https://shop.example.com/%s", product),
        )
        request.SetName(fmt.Sprintf("Product: %s", product))
        request.SetTags([]string{"catalog", "automated"})

        response, _, err := client.LinksAPI.LinksServiceCreate(ctx).
            CreateLinkRequest(*request).Execute()
        if err != nil {
            fmt.Printf("Error creating %s: %v\n", product, err)
            continue
        }
        fmt.Printf("%s: %s\n", product, response.Link.Shortlink)
    }
}

Strengths:

  • Full type safety and IDE autocomplete
  • Fine-grained error handling with status codes and retry logic
  • Integrates directly into application code
  • Best performance for high-throughput operations
  • Five language choices: TypeScript, Python, Go, Java, Rust

Trade-offs:

  • Requires writing and maintaining code
  • Needs deployment infrastructure (CI/CD, hosting)
  • SDK updates must be tracked and applied

Approach 2: CLI scripting

The Linkbreakers CLI provides a terminal-based interface for all core platform operations. It is designed to work in three contexts: interactive terminal use by humans, shell scripts and cron jobs, and as a tool surface for AI agents operating in terminal environments.

How it works:

Install the CLI binary, authenticate with a workspace token, and run commands. Output defaults to human-readable tables but can switch to JSON with the --output json flag for machine consumption.

Creating a link:

Bash
linkbreakers links create \
  --destination https://shop.example.com/product-42 \
  --name "Product 42 Launch" \
  --tags product-launch,q3-2026

Listing links as JSON for scripting:

Bash
linkbreakers links list --page-size 50 --output json | jq '.links[].shortlink'

Shell script for campaign deployment:

Bash
#!/bin/bash
# deploy-campaign.sh — create links for each URL in a file

CAMPAIGN_TAG="summer-sale-2026"

while IFS=, read -r name url; do
  RESULT=$(linkbreakers links create \
    --destination "$url" \
    --name "$name" \
    --tags "$CAMPAIGN_TAG" \
    --output json)

  SHORT_URL=$(echo "$RESULT" | jq -r '.link.shortlink')
  echo "$name -> $SHORT_URL"
done < campaign-urls.csv

Domain verification in CI/CD:

Bash
# Check that custom domain DNS is configured correctly
linkbreakers custom-domains check my-domain-id --output json | jq '.status'

Strengths:

  • No code compilation or dependency management
  • Works in any shell environment (bash, zsh, PowerShell)
  • Integrates with CI/CD pipelines (GitHub Actions, GitLab CI, Jenkins)
  • JSON output pipes into jq, awk, or any text processing tool
  • Self-updating: linkbreakers self-update

Trade-offs:

  • Limited to operations the CLI exposes (covers core features, not every API endpoint)
  • Shell scripting has weaker error handling than SDK code
  • Not suitable for embedding in application code that runs in production

Approach 3: MCP AI agents

The MCP server enables AI assistants to interact with Linkbreakers through natural language. Instead of writing code or shell commands, you describe what you want and the AI translates your intent into API calls.

How it works:

Configure an MCP-compatible AI client (Claude Code, Claude Desktop, Continue) with the Linkbreakers MCP server URL. Your client handles OAuth sign-in automatically. The AI discovers available operations and calls them during conversation.

Setup for Claude Code (one command):

Bash
claude mcp add --transport http linkbreakers https://mcp.linkbreakers.com

Setup for Claude Desktop (JSON config):

JSON
{
  "mcpServers": {
    "linkbreakers": {
      "url": "https://mcp.linkbreakers.com"
    }
  }
}

Creating a link:

"Create a tracked link for https://shop.example.com/product-42 with slug 'product-42', name 'Product 42 Launch', and tags 'product-launch' and 'q3-2026'."

Building a multi-step workflow:

"Add a workflow to the Product 42 link. First step: show a form collecting name and email. Second step: redirect to the product details page at https://shop.example.com/product-42/details. Connect them in sequence."

Pulling analytics:

"How many scans did my links tagged 'summer-sale-2026' receive this week? Break it down by link."

Bulk operations:

"Create 30 tracked links, one for each store location. Here are the names and URLs: [list]. Tag all of them with 'retail-2026' and use the store name as the slug."

Strengths:

  • No code, no scripts, no deployment — purely conversational
  • Non-technical team members can perform programmatic operations
  • AI can chain multiple operations intelligently (create link, add steps, wire relationships)
  • Ideal for one-time setup, prototyping, and exploration
  • Fastest path from idea to execution for ad-hoc tasks

Trade-offs:

  • Not deterministic — the AI may interpret ambiguous prompts differently each time
  • Not suitable for scheduled or recurring automation (no cron-like capability)
  • Requires an MCP-compatible AI client
  • Rate limits apply; high-volume operations may need the SDK instead

Feature comparison table

Capability REST API + SDK CLI MCP AI agents
Create links All SDKs links create Natural language
Bulk link creation SDK loop or links_create_bulk Shell script loop Conversational batch
Workflow steps Full CRUD Via raw command Full CRUD
QR code designs Full CRUD Not available Full CRUD
QR code templates Full CRUD Not available Full CRUD
Analytics/events Query with filters Via raw command Conversational query
Visitor tracking Frontend + backend Not available Query only
Custom domains Full CRUD custom-domains commands Full CRUD
Media management Full CRUD Not available Full CRUD
Page themes Full CRUD Not available Full CRUD
Type safety Full (TS, Go, Java, Rust) N/A N/A
Error handling Programmatic (try/catch) Exit codes + stderr AI explains and retries
CI/CD integration Native Native Not designed for CI/CD
Scheduled execution Cron + SDK Cron + CLI Not supported
Non-technical users Requires code Requires terminal Conversational
Setup time 10-30 minutes 5 minutes 2 minutes

When to use each approach

Use the REST API + SDKs when

You are building a production application that programmatically creates links, generates QR codes, or tracks visitors. Examples:

  • An e-commerce platform that generates a unique QR code for each order
  • A SaaS product that creates tracked links for customer onboarding emails
  • A data pipeline that pulls scan analytics into a business intelligence dashboard
  • A mobile app that creates contact cards on behalf of users

The SDK gives you type safety, fine-grained error handling, and the ability to integrate QR code operations directly into your application logic. Choose the SDK in the language your application is written in.

Use CLI scripting when

You are automating infrastructure or operations tasks that run in a terminal or CI/CD environment. Examples:

  • A deployment script that creates campaign links as part of a release process
  • A cron job that checks custom domain DNS status every hour
  • A GitHub Action that creates a tracked link for each new release
  • A one-liner to list all links and pipe them into a spreadsheet

The CLI requires no code compilation, no dependency management, and no SDK installation. It works in any shell and integrates with standard Unix tools.

Use MCP AI agents when

You need to perform ad-hoc operations conversationally without writing code or running scripts. Examples:

  • A marketing manager setting up a campaign with tagged links, workflows, and conditional routing
  • A developer prototyping a customer journey before implementing it in code
  • A team lead pulling analytics for a weekly report through conversation
  • A non-technical user creating contact cards for the sales team

MCP removes the barrier between intent and execution. You describe the outcome you want, and the AI figures out the API calls.

Combining approaches on one platform

The unique advantage of Linkbreakers is that all three approaches operate on the same workspace data. This means you can use the best tool for each task without worrying about synchronization or data silos.

Practical combination example:

  1. MCP — A marketing manager uses Claude Desktop to set up a new campaign: creates 15 tracked links, builds a workflow with a form and conditional routing, and generates QR code designs.

  2. Dashboard — The designer opens the Linkbreakers dashboard to refine the QR code colors and preview the form layout.

  3. SDK — A developer writes a TypeScript integration that uses the Linkbreakers SDK to identify visitors on the campaign landing page and enrich their profiles with purchase data.

  4. CLI — A DevOps engineer adds a step to the CI/CD pipeline that verifies custom domain DNS status before each deployment.

  5. MCP — At the end of the quarter, the marketing manager asks Claude Code for a performance breakdown of all links tagged with the campaign name.

Every step operates on the same links, the same workflows, and the same analytics data. No data migration, no sync issues, no duplicate records.

Performance considerations

API + SDK performance

  • Direct HTTP calls with minimal overhead
  • Connection pooling available in most SDK languages
  • Supports concurrent requests for parallel operations
  • Best choice for high-throughput scenarios (hundreds or thousands of links)

CLI performance

  • Each command is a separate HTTP request
  • Shell script loops add process spawning overhead
  • Suitable for dozens to low hundreds of operations
  • JSON output adds minimal parsing overhead

MCP performance

  • Each operation routes through the MCP server (one additional hop)
  • The MCP server is stateless and adds sub-100ms overhead
  • AI processing time adds latency to each prompt-response cycle
  • Best for single to dozens of operations per conversation
  • For hundreds+ operations, use bulk SDK calls instead

Throughput guidance

Volume Recommended approach
1-10 operations MCP or CLI
10-100 operations CLI script or MCP bulk prompt
100-1,000 operations SDK with concurrency
1,000+ operations SDK with bulk endpoints and retry logic

Code examples summary

SDK (TypeScript):

TypeScript
const response = await linksApi.linksServiceCreate({
  createLinkRequest: {
    destination: 'https://example.com',
    name: 'My Link',
    tags: ['demo'],
  },
});

CLI:

Bash
linkbreakers links create \
  --destination https://example.com \
  --name "My Link" \
  --tags demo

MCP (natural language):

"Create a tracked link for https://example.com named 'My Link' with tag 'demo'."

All three produce the same result: a tracked short link in your Linkbreakers workspace with a QR code, analytics tracking, and the specified tag.

Build a workflow — three ways

SDK (Python):

Python
# Create form step
form = workflow_api.workflow_steps_service_create(
    create_workflow_step_request={
        'link_id': link_id,
        'type': 'FORM',
        'config': {
            'fields': [
                {'name': 'email', 'type': 'email', 'required': True},
            ],
        },
    }
)

# Create redirect step
redirect = workflow_api.workflow_steps_service_create(
    create_workflow_step_request={
        'link_id': link_id,
        'type': 'REDIRECT',
        'config': {'url': 'https://example.com/thanks'},
    }
)

# Connect steps
workflow_api.workflow_steps_service_create_relationship(
    create_relationship_request={
        'parent_step_id': form.workflow_step.id,
        'child_step_id': redirect.workflow_step.id,
    }
)

CLI:

Bash
# CLI supports link operations; for workflow steps, use the raw API mode
linkbreakers raw POST /v1/workflow-steps \
  --data '{"linkId":"LINK_ID","type":"FORM","config":{"fields":[{"name":"email","type":"email","required":true}]}}'

MCP (natural language):

"Add a form step collecting email to my link, then redirect to https://example.com/thanks."

Pull analytics — three ways

SDK (TypeScript):

TypeScript
const events = await eventsApi.eventsServiceList({
  linkId: 'LINK_ID',
  startDate: '2026-06-01T00:00:00Z',
  endDate: '2026-06-30T23:59:59Z',
});
console.log(`Total scans: ${events.events.length}`);

CLI:

Bash
linkbreakers raw GET "/v1/events?linkId=LINK_ID&startDate=2026-06-01T00:00:00Z" \
  --output json | jq '.events | length'

MCP (natural language):

"How many scans did link LINK_ID receive in June 2026?"

Frequently asked questions

Can I switch between approaches without losing data? Yes. All three approaches connect to the same Linkbreakers API and workspace. A link created via SDK is visible in the CLI and MCP, and vice versa. There is no data migration required when switching approaches.

Which approach should a non-developer choose? MCP AI agents. No code, no terminal knowledge needed — just a one-time configuration. Describe what you need in plain language and the AI handles the rest.

Can I use the SDK and MCP in the same project? Yes. A common pattern is to use the SDK for production application logic (visitor tracking, link creation in response to user actions) and MCP for ad-hoc operations (campaign setup, analytics queries, debugging).

Is the REST API documented separately from the SDKs? Yes. Full API documentation is available at linkbreakers.com/help/api. Each SDK mirrors the API structure but uses language-native conventions (snake_case in Python, camelCase in TypeScript, PascalCase in Go).

Do all three approaches support custom domains? Yes. You can add, verify, and manage custom domains through the SDK, CLI, and MCP. The CLI provides dedicated custom-domains commands. The SDK and MCP use the domains API endpoints.

What authentication does each approach use? The SDK uses secret keys (JWT tokens). The CLI uses workspace tokens set via linkbreakers auth set-token. The MCP server uses OAuth 2.0 — your client handles sign-in automatically and no token configuration is needed. SDK and CLI credential types are created in Dashboard > Settings > API Tokens.

Getting started

Limits and caveats

  • API rate limits apply equally across all three approaches. Limits vary by plan.
  • The CLI does not expose every API endpoint. For operations not covered by CLI commands, use linkbreakers raw for direct API access.
  • MCP is not designed for scheduled or recurring automation. Use SDK or CLI for cron-based workflows.
  • SDK error handling is more granular than CLI exit codes or MCP AI explanations. Use SDKs when precise error recovery is critical.
  • Visual QR code design preview is only available in the dashboard. All three programmatic approaches configure design parameters but do not render previews.
  • Feature availability and limits can vary by plan and workspace setup.
  • SDKs require secret keys and the CLI requires workspace tokens, both created in Dashboard > Settings > API Tokens. The MCP server uses OAuth 2.0 and does not require manual token configuration.

Last reviewed

This article was last reviewed on June 6, 2026.

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.