QR for Agent Documentation

Everything you need to create, update, and track dynamic QR codes -- via MCP or REST API.

Quick Start

From zero to your first QR code in 30 seconds.

1

Install the MCP server

$ npx qr-for-agent

Works with Claude Desktop, Cursor, and any MCP-compatible client.

2

Get your API key

Get Your API Key

Your key follows the format qr_ + 32-character random string. Keep it in your environment variables.

3

Create your first QR code

Ask your agent:

Prompt
Create a dynamic QR code for https://example.com

Or call the REST API directly:

Request
$ curl -X POST https://api.qragentcore.com/api/qr \
  -H "Content-Type: application/json" \
  -H "X-API-Key: qr_YOUR_KEY_HERE" \
  -d '{"target_url": "https://example.com", "label": "My first QR"}'
Response
{
  "id": 1,
  "short_id": "wkQ5W-fm",
  "short_url": "https://api.qragentcore.com/r/wkQ5W-fm",
  "target_url": "https://example.com",
  "label": "My first QR",
  "format": "svg",
  "image_data": "<svg>...</svg>",
  "created_at": "2026-02-24T10:00:00.000Z"
}

That's it. One command, one API call, one QR code. The short URL redirects to your target -- and you can change the target later without regenerating the image.

MCP Setup

QR for Agent ships as a standalone MCP server on npm. One package, 37 tools, 3 dependencies.

Claude Desktop

Add to your claude_desktop_config.json:

claude_desktop_config.json
{
  "mcpServers": {
    "qr-for-agent": {
      "command": "npx",
      "args": ["-y", "qr-for-agent"],
      "env": {
        "API_KEY": "your-api-key",
        "BASE_URL": "https://api.qragentcore.com"
      }
    }
  }
}

Restart Claude Desktop. Your agent now has 37 tools available.

Cursor

Add to .cursor/mcp.json in your project root:

.cursor/mcp.json
{
  "mcpServers": {
    "qr-for-agent": {
      "command": "npx",
      "args": ["-y", "qr-for-agent"],
      "env": {
        "API_KEY": "your-api-key",
        "BASE_URL": "https://api.qragentcore.com"
      }
    }
  }
}

Reload the window. The tools appear in Cursor's MCP panel.

Any MCP client

The server runs via npx qr-for-agent and communicates over stdio. Any client that supports the MCP standard can use it. Set API_KEY and BASE_URL as environment variables.

API Reference

All /api/* endpoints require an X-API-Key header. Public endpoints (/r/*, /i/*) don't require auth.

QR Code Endpoints

Method Path Description Auth
POST /api/qr Create a new dynamic QR code Yes
GET /api/qr List all QR codes (paginated) Yes
GET /api/qr/:shortId Get QR code details Yes
PATCH /api/qr/:shortId Update target URL or label Yes
DELETE /api/qr/:shortId Delete QR code and analytics Yes
GET /api/qr/:shortId/image Download QR image Yes
POST /api/qr/bulk Create up to 50 QR codes at once Yes
PATCH /api/qr/bulk Update up to 50 QR codes at once Yes
DELETE /api/qr/bulk Delete up to 50 QR codes at once Yes

Analytics Endpoint

Method Path Description Auth
GET /api/analytics/:shortId Scan count and recent events Yes

Webhook Endpoints

Method Path Description Auth
POST /api/webhooks Register a webhook endpoint Yes
GET /api/webhooks List all webhooks Yes
DELETE /api/webhooks/:id Delete a webhook Yes

Account Endpoints

Method Path Description Auth
POST /api/register Register for an API key No
GET /api/usage Get current usage and quota Yes
POST /api/stripe/checkout Create Stripe Checkout session for Pro upgrade Yes
POST /api/stripe/portal Open Stripe billing portal Yes

Public Endpoints

Method Path Description Auth
GET /r/:shortId Redirect to target URL (records scan) No
GET /i/:shortId Serve QR image (cacheable) No
GET /health Health check No
GET /documentation Swagger UI (OpenAPI docs) No

POST /api/qr -- Create a QR code

Request body:

Parameter Type Required Default Description
target_url string Yes -- The destination URL. Must be a fully-qualified absolute URL.
label string No null A human-readable label for organizing QR codes.
format string No "svg" Image format: "svg" (recommended) or "png".
foreground_color string No "#000000" Hex color for QR code dots.
background_color string No "#ffffff" Hex color for QR code background.
dot_style string No "square" "square", "rounded", "dots", or "classy-rounded".
corner_style string No "square" "square", "extra-rounded", or "dot".
logo_url string No -- URL to a logo image (PNG/JPG/SVG) or data: URI. Centered on the QR code.
logo_size number No 0.2 Logo size as ratio of QR width (0.15-0.3).
width integer No 400 QR code width in pixels (200-2000).
margin integer No 2 Quiet zone margin in modules (0-10).
error_correction string No "M" "L" (7%), "M" (15%), "Q" (25%), "H" (30%). Auto-set to H with logo.
expires_at string No -- ISO 8601 date-time. After this date, scanning returns 410 Gone instead of redirecting.
scheduled_url string No -- Replacement URL that activates at scheduled_at.
scheduled_at string No -- ISO 8601 date-time. When reached, target automatically switches to scheduled_url.

Basic request:

Request
$ curl -X POST https://api.qragentcore.com/api/qr \
  -H "Content-Type: application/json" \
  -H "X-API-Key: qr_YOUR_KEY" \
  -d '{
    "target_url": "https://conf.example.com/2026",
    "label": "Conference landing page",
    "format": "svg"
  }'

Styled request (colors, rounded dots, logo):

Styled Request
$ curl -X POST https://api.qragentcore.com/api/qr \
  -H "Content-Type: application/json" \
  -H "X-API-Key: qr_YOUR_KEY" \
  -d '{
    "target_url": "https://conf.example.com/2026",
    "label": "Branded QR",
    "foreground_color": "#4F46E5",
    "background_color": "#F9FAFB",
    "dot_style": "rounded",
    "corner_style": "extra-rounded",
    "logo_url": "https://example.com/logo.png",
    "logo_size": 0.25
  }'

Response (201):

Response
{
  "id": 1,
  "short_id": "wkQ5W-fm",
  "short_url": "https://api.qragentcore.com/r/wkQ5W-fm",
  "target_url": "https://conf.example.com/2026",
  "label": "Conference landing page",
  "format": "svg",
  "image_data": "<svg>...</svg>",
  "created_at": "2026-02-24T10:00:00.000Z"
}

QR Types

QR for Agent supports 11 types of QR codes: URL, vCard, WiFi, Email, SMS, Phone, Event/Calendar, Text, Location, Social Media, and App Store. Each type determines how the /r/:shortId endpoint behaves when scanned.

Type Redirect Behavior Use Case
url 302 redirect to target URL Standard dynamic links (default)
vcard Serves .vcf file (vCard 3.0 format) Digital business cards, contact info
wifi Returns WiFi network credentials WiFi network sharing
email Opens mail client with pre-filled email Contact forms, support requests
sms Opens SMS app with pre-filled message Marketing campaigns, quick responses
phone Initiates phone call Customer support, contact buttons
event Opens calendar with event details Event invitations, appointments
text Displays plain text content Instructions, codes, messages
location Opens map app with coordinates Directions, venue locations
social Landing page with social media links Link-in-bio, social profiles
app_store Smart redirect to iOS/Android store App downloads, store links

Create a vCard QR code:

vCard Request
$ curl -X POST https://api.qragentcore.com/api/qr \
  -H "Content-Type: application/json" \
  -H "X-API-Key: qr_YOUR_KEY" \
  -d '{
    "type": "vcard",
    "target_url": "John Doe|Acme Corp|CEO|+1234567890|[email protected]|https://acme.com",
    "label": "John Doe Business Card",
    "format": "svg"
  }'

The target_url field for vCard should contain pipe-separated values: Name|Organization|Title|Phone|Email|Website. When scanned, the QR code serves a .vcf file that opens in the phone's contact app.

Create a WiFi QR code:

WiFi Request
$ curl -X POST https://api.qragentcore.com/api/qr \
  -H "Content-Type: application/json" \
  -H "X-API-Key: qr_YOUR_KEY" \
  -d '{
    "type": "wifi",
    "target_url": "MyNetwork|WPA|mypassword123|false",
    "label": "Office WiFi",
    "format": "svg"
  }'

The target_url field for WiFi should contain pipe-separated values: SSID|Security|Password|Hidden. Security can be "WPA", "WEP", or "nopass". Hidden is "true" or "false". When scanned, the QR code returns JSON with WiFi credentials that the phone's OS can use to auto-join the network.

PATCH /api/qr/:shortId -- Update destination

The QR image stays the same. Only the redirect target changes. This is the core dynamic link feature.

Request
$ curl -X PATCH https://api.qragentcore.com/api/qr/wkQ5W-fm \
  -H "Content-Type: application/json" \
  -H "X-API-Key: qr_YOUR_KEY" \
  -d '{"target_url": "https://new-destination.com"}'

Expiration & Scheduled URL Swap

Set an expiration date to automatically disable a QR code, or schedule a URL swap to change where it points at a future date. Both are checked at scan time -- no cron jobs needed.

Create a QR code that expires:

Expiring QR
$ curl -X POST https://api.qragentcore.com/api/qr \
  -H "Content-Type: application/json" \
  -H "X-API-Key: qr_YOUR_KEY" \
  -d '{
    "target_url": "https://example.com/flash-sale",
    "label": "Flash sale - 48h only",
    "expires_at": "2026-04-01T00:00:00.000Z"
  }'

After expires_at, scanning returns 410 Gone with a QR_EXPIRED code. Remove the expiration anytime via PATCH (expires_at: null).

Schedule a URL swap:

Scheduled Swap
$ curl -X POST https://api.qragentcore.com/api/qr \
  -H "Content-Type: application/json" \
  -H "X-API-Key: qr_YOUR_KEY" \
  -d '{
    "target_url": "https://example.com/pre-launch",
    "scheduled_url": "https://example.com/product-page",
    "scheduled_at": "2026-04-15T09:00:00.000Z",
    "label": "Product launch QR"
  }'

Before the date, scans go to target_url. After the date, the first scan triggers the swap -- target_url becomes scheduled_url permanently. Cancel anytime via PATCH (scheduled_url: null, scheduled_at: null).

GET /api/qr -- List QR codes

Query parameters:

Parameter Type Default Description
limit integer 20 Max results (1-100).
offset integer 0 Number of records to skip.
Request
$ curl https://api.qragentcore.com/api/qr?limit=10&offset=0 \
  -H "X-API-Key: qr_YOUR_KEY"

GET /api/analytics/:shortId -- Enriched scan analytics

Returns scan statistics with aggregations by device, browser, country, referer, and daily trends. Supports ?period=7d|30d|90d|all (default: 30d). User-agent is parsed and IPs are geolocated at scan time.

Request
$ curl https://api.qragentcore.com/api/analytics/wkQ5W-fm?period=30d \
  -H "X-API-Key: qr_YOUR_KEY"

Response:

Response
{
  "short_id": "wkQ5W-fm",
  "total_scans": 142,
  "period": "30d",
  "scans_by_day": [
    { "date": "2026-02-26", "count": 12 },
    { "date": "2026-02-27", "count": 8 }
  ],
  "top_devices": [
    { "device_type": "mobile", "count": 89, "percentage": 62.7 },
    { "device_type": "desktop", "count": 45, "percentage": 31.7 }
  ],
  "top_browsers": [
    { "browser": "Chrome", "count": 65, "percentage": 45.8 },
    { "browser": "Safari", "count": 42, "percentage": 29.6 }
  ],
  "top_countries": [
    { "country": "FR", "count": 80, "percentage": 56.3 },
    { "country": "US", "count": 30, "percentage": 21.1 }
  ],
  "top_referers": [
    { "referer": "instagram.com", "count": 30, "percentage": 21.1 },
    { "referer": "(direct)", "count": 25, "percentage": 17.6 }
  ],
  "recent_scans": [
    {
      "scanned_at": "2026-02-27T14:32:00.000Z",
      "user_agent": "Mozilla/5.0 ...",
      "referer": "https://instagram.com/",
      "device_type": "mobile",
      "browser": "Safari",
      "os": "iOS",
      "country": "FR",
      "city": "Paris"
    }
  ]
}

DELETE /api/qr/:shortId -- Delete a QR code

Permanently removes the QR code and all associated scan analytics. The short URL stops working immediately. This cannot be undone.

Request
$ curl -X DELETE https://api.qragentcore.com/api/qr/wkQ5W-fm \
  -H "X-API-Key: qr_YOUR_KEY"

POST /api/webhooks -- Register a webhook

Register an endpoint to receive real-time POST notifications when your QR codes are scanned. Returns an HMAC-SHA256 secret for signature verification -- store it securely, it is only shown once.

Request body:

Parameter Type Required Default Description
url string Yes -- The HTTP/HTTPS endpoint that will receive webhook events.
events string[] No ["qr.scanned"] Events to subscribe to: "qr.scanned", "qr.conversion".
Request
$ curl -X POST https://api.qragentcore.com/api/webhooks \
  -H "Content-Type: application/json" \
  -H "X-API-Key: qr_YOUR_KEY" \
  -d '{"url": "https://your-server.com/webhook"}'

Response (201):

Response
{
  "id": 1,
  "url": "https://your-server.com/webhook",
  "secret": "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
  "events": ["qr.scanned"],
  "is_active": true,
  "created_at": "2026-02-27T10:00:00.000Z"
}

Webhook payload (sent to your endpoint):

Webhook Event
{
  "event": "qr.scanned",
  "timestamp": "2026-02-27T14:32:00.000Z",
  "data": {
    "short_id": "wkQ5W-fm",
    "target_url": "https://example.com",
    "label": "My QR",
    "scan": {
      "user_agent": "Mozilla/5.0 ...",
      "referer": null,
      "ip": "203.0.113.42",
      "scanned_at": "2026-02-27T14:32:00.000Z"
    }
  }
}

Verifying signatures:

Every webhook request includes an X-Webhook-Signature header containing an HMAC-SHA256 hex digest of the request body, signed with your webhook secret.

Signature verification (Node.js)
import crypto from "node:crypto";

function verifySignature(body, signature, secret) {
  const expected = crypto
    .createHmac("sha256", secret)
    .update(body)
    .digest("hex");
  return signature === expected;
}

GET /t/:shortId -- Tracking pixel (conversion)

Zero-JavaScript conversion tracking. Embed this URL as an invisible image on your thank-you page. Returns a 1×1 transparent GIF. No authentication required -- the short ID scopes the event to your QR code.

Query parameters:

Parameter Type Required Description
event string Yes Event name (e.g. "purchase", "signup", "lead").
value number No Monetary value of the conversion.
HTML embed
<img src="https://api.qragentcore.com/t/wkQ5W-fm?event=purchase&value=49.99" width="1" height="1" alt="" />

POST /api/conversions -- Record a conversion

Record a conversion event programmatically. Use this when server-side tracking is preferred over the pixel approach.

Request
$ curl -X POST https://api.qragentcore.com/api/conversions \
  -H "Content-Type: application/json" \
  -H "X-API-Key: qr_YOUR_KEY" \
  -d '{"short_id": "wkQ5W-fm", "event": "purchase", "value": 49.99}'

Response (201):

Response
{
  "id": 1,
  "qr_code_id": 42,
  "event_name": "purchase",
  "value": "49.99",
  "created_at": "2026-03-02T10:00:00.000Z"
}

GET /api/conversions/:shortId -- Conversion stats

Get conversion analytics for a QR code: totals, breakdowns by event name, daily trends, and recent events. Supports period filtering.

Request
$ curl https://api.qragentcore.com/api/conversions/wkQ5W-fm?period=30d \
  -H "X-API-Key: qr_YOUR_KEY"

Response (200):

Response
{
  "short_id": "wkQ5W-fm",
  "total_conversions": 42,
  "total_value": 1250.50,
  "period": "30d",
  "by_event": [
    { "event_name": "purchase", "count": 30, "total_value": 1200.00 },
    { "event_name": "signup", "count": 12, "total_value": 50.50 }
  ],
  "by_day": [
    { "date": "2026-03-01", "count": 5, "total_value": 200.00 }
  ],
  "recent_events": [
    {
      "event_name": "purchase",
      "value": "49.99",
      "metadata": {},
      "created_at": "2026-03-02T10:00:00.000Z"
    }
  ]
}

Authentication

All /api/* endpoints require an X-API-Key header.

  • Format: qr_ + 32-character random string
  • Multi-tenant: each API key only sees its own QR codes
  • Isolation: no data leaks between API keys -- build agents for multiple clients safely

MCP Tools

37 tools. No context bloat, no "too many tools" problem. Each tool maps 1:1 to a REST endpoint.

QR Code Tools

Tool Key Parameters Description
create_qr_code target_url, format, dot_style, corner_style, foreground_color, logo_url, ... Create a custom-styled dynamic QR code.
get_qr_code short_id Retrieve details and metadata for an existing QR code.
update_qr_destination short_id, target_url, label Change redirect target without regenerating the image.
list_qr_codes limit, offset List all QR codes with pagination.
delete_qr_code short_id Delete a QR code and its scan analytics.
get_qr_analytics short_id Get scan count and recent scan events.
create_vcard_qr name, email, phone, organization, ... Create a contact card QR code with name, email, phone, organization, etc.
create_wifi_qr ssid, password, encryption Create a WiFi QR code with SSID, password, and encryption type.
create_email_qr email, subject, body Create a pre-filled email QR code.
create_sms_qr phone, message Create a pre-filled SMS QR code.
create_phone_qr phone Create a phone call QR code.
create_event_qr title, start, end, location, ... Create a calendar event QR code.
create_text_qr text Create a plain text QR code.
create_location_qr latitude, longitude, name Create a map location QR code.
create_social_qr title, links[] Create a social media links QR code.
create_app_store_qr ios_url, android_url Create a smart app store redirect QR code.
update_vcard_qr short_id, name, email, phone, ... Update contact fields on a vCard QR code (partial merge).
update_wifi_qr short_id, ssid, password, ... Update WiFi credentials on a WiFi QR code (partial merge).
update_social_qr short_id, links[] Update social media links.
update_app_store_qr short_id, ios_url, android_url Update app store URLs.
bulk_create_qr_codes items[] (target_url, label, format, style...) Create up to 50 QR codes in one request.
bulk_update_qr_codes items[] (short_id, target_url, label) Update up to 50 QR codes in one request.
bulk_delete_qr_codes short_ids[] Delete up to 50 QR codes in one request.
bulk_create_from_csv csv_content Create up to 500 QR codes from CSV data. Pro only.
set_utm_params short_id, utm_source, utm_medium, utm_campaign, ... Set UTM tracking parameters on a URL QR code.
set_redirect_rules short_id, rules[] Set conditional redirect rules on a URL QR code (device, OS, country, language, time, A/B).

Webhook Tools

Tool Key Parameters Description
create_webhook url, events Register an endpoint for real-time scan notifications (HMAC-signed).
list_webhooks -- List all registered webhook endpoints.
delete_webhook webhook_id Remove a webhook endpoint.

Conversion Tools

Tool Key Parameters Description
record_conversion short_id, event, value Record a conversion event (purchase, signup) for a QR code.
get_conversions short_id, period Get conversion stats: totals, by event, by day, recent events.

Domain Tools

Tool Key Parameters Description
set_custom_domain domain Set a custom domain for branded short URLs. Pro only.
get_custom_domain -- Get current custom domain and DNS verification status.

Account Tools

Tool Key Parameters Description
register email, label Register for an API key with your email.
get_usage -- Get current usage and quota for your API key.
upgrade_to_pro -- Upgrade to Pro ($19/month) -- returns a Stripe Checkout URL.
manage_billing -- Open Stripe billing portal to manage subscription.

Tool details

create_qr_code

Creates a custom-styled QR code with full control over appearance: colors, dot shapes (square, rounded, dots, classy-rounded), corner shapes (square, extra-rounded, dot), and optional logo embedding. The QR code points to a short URL that redirects to your target. Change the target later without regenerating the image.

update_qr_destination

This is the key "dynamic link" feature: the QR image stays the same, but scanning it goes to the new URL. Use it to update campaigns, fix broken links, or A/B test landing pages.

create_webhook

Register a webhook endpoint to get real-time notifications when any of your QR codes is scanned. Each webhook delivery is signed with HMAC-SHA256 for verification. The secret is only returned at creation time.

get_qr_analytics

Returns enriched scan analytics with breakdowns by device, browser, country, referer, and daily trends. Supports a period parameter (7d, 30d, 90d, all). User-agents are parsed and IPs geolocated at scan time — your agent gets structured data, not raw strings.

record_conversion

Track post-scan events like purchases, signups, or leads. Pair with the zero-JS tracking pixel (GET /t/:shortId?event=purchase&value=49.99) for server-free conversion tracking, or call the API directly from your backend.

bulk_create_from_csv

Create up to 500 QR codes from CSV data in a single call. Pro only. Each row maps to a QR code with support for all style options, types, and frames. Row-level validation with error line numbers.

Environment Variables

MCP Server (qr-for-agent)

Variable Required Default Description
API_KEY Yes -- Your QR for Agent API key. Format: qr_ + 32 chars.
BASE_URL No http://localhost:3100 The URL of your QR for Agent instance. Use https://api.qragentcore.com for the hosted service.

Self-Hosted Server

Variable Required Default Description
PORT No 3100 HTTP port.
HOST No 0.0.0.0 Bind address.
BASE_URL No http://localhost:3100 Public URL used in generated short URLs. Set this to your domain.
DATABASE_URL No ./data/qr-agent.db SQLite file path.
SHORT_ID_LENGTH No 8 Length of generated short IDs.

Self-Hosting

QR for Agent is open source and MIT-licensed. Run it on your own infrastructure or use the hosted service. Your call.

Docker

$ git clone https://github.com/benswel/qr-agent-core.git
$ cd qr-agent-core
$ docker compose up -d

The database is persisted in a Docker volume. Your server runs at http://localhost:3100.

On first startup, an API key is auto-generated and printed to the console. Use docker compose logs to retrieve it.

docker-compose.yml:

docker-compose.yml
services:
  qr-agent-core:
    build: .
    ports:
      - "3100:3100"
    volumes:
      - qr-data:/app/data
    environment:
      - PORT=3100
      - HOST=0.0.0.0
      - BASE_URL=https://your-domain.com
      - DATABASE_URL=/app/data/qr-agent.db
    restart: unless-stopped

volumes:
  qr-data:

Railway

The project includes railway.toml and a multi-stage Dockerfile. Deploy in three steps:

  1. Fork the repo on GitHub
  2. Connect it to Railway
  3. Railway builds and deploys automatically with health checks on /health

Set BASE_URL to your Railway domain in the environment variables.

Without Docker

$ git clone https://github.com/benswel/qr-agent-core.git
$ cd qr-agent-core
$ npm install
$ npm run dev

On first startup, an API key is auto-generated and printed to the console.

Managing API keys:

$ npm run key:create "my-label"   # Create a new API key
$ npm run key:list                 # List all API keys

Teams keep rebuilding small but critical utilities -- QR codes, short URLs, tokens -- over and over again. We built it once, correctly, and opened the source.

View on GitHub

Start building

Free tier. Full API access. No credit card.

$ npx qr-for-agent

Questions? Open an issue on GitHub or check the OpenAPI docs (Swagger UI).