Skip to main content

REST API
for QR Track.

Programmatic access to dynamic QR code creation, listing, retrieval, and updates. Free with every self-hosted install. No paid tier, no per-call billing.

Authentication

All requests require an X-Api-Key header. Generate keys in Settings → API Keys. Keys are scoped per user and can be revoked at any time.

X-Api-Key: qrt_a1b2c3d4e5f6789...

The API key is never sent to the browser when you use the built-in Live Console — it’s injected server-side, then logs the call.

Base URL

https://qr.yoursite.com/api.php

Endpoints

List all QR codes

GET /api.php

Response:
{
  "codes": [
    {
      "uuid": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
      "type": "url",
      "destination": "https://example.com/promo-summer",
      "scans": 142,
      "created_at": "2026-04-15T18:24:11Z",
      "logo": null
    },
    ...
  ]
}

Get one code by UUID

GET /api.php?uuid={uuid}

Response includes scan log:
{
  "uuid": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "type": "url",
  "destination": "https://example.com/promo-summer",
  "scans": [
    {"timestamp":"2026-04-26T14:02:11Z","city":"Tampa","country":"US","device":"iPhone"},
    {"timestamp":"2026-04-26T14:05:48Z","city":"Tampa","country":"US","device":"Android"}
  ]
}

Create a new code

POST /api.php
Content-Type: application/json

{
  "type": "url",
  "destination": "https://example.com/my-page",
  "label": "Summer promo"
}

Response:
{
  "uuid": "...",
  "short_url": "https://qr.yoursite.com/p/abc123",
  "qr_image_url": "https://qr.yoursite.com/img/abc123.png"
}

Update destination

POST /api.php?uuid={uuid}
Content-Type: application/json

{
  "destination": "https://example.com/new-destination"
}

Code examples

curl

# Create a code
curl -X POST https://qr.yoursite.com/api.php \
     -H "X-Api-Key: $QRT_KEY" \
     -H "Content-Type: application/json" \
     -d '{"type":"url","destination":"https://example.com","label":"Test"}'

PHP

$ch = curl_init('https://qr.yoursite.com/api.php');
curl_setopt_array($ch, [
    CURLOPT_POST           => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['X-Api-Key: ' . $apiKey, 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS     => json_encode(['type'=>'url','destination'=>'https://example.com']),
]);
$response = json_decode(curl_exec($ch), true);

Python

import requests, os
r = requests.post(
    'https://qr.yoursite.com/api.php',
    headers={'X-Api-Key': os.environ['QRT_KEY']},
    json={'type': 'url', 'destination': 'https://example.com', 'label': 'Test'}
)
print(r.json())

JavaScript (Node fetch)

const r = await fetch('https://qr.yoursite.com/api.php', {
    method: 'POST',
    headers: {
        'X-Api-Key': process.env.QRT_KEY,
        'Content-Type': 'application/json'
    },
    body: JSON.stringify({ type: 'url', destination: 'https://example.com' })
});
const data = await r.json();

Rate limits

Default is 60 requests per minute per API key. Configure via API_RATE_LIMIT in TiCore/.env. Exceeded requests return HTTP 429 with a Retry-After header.

Frequently Asked Questions

Yes. Every self-hosted install includes a REST API for listing codes, fetching one by UUID, and creating new dynamic codes. The API is free — no paid tier required.

Log into your QR Track dashboard, open Settings → API Keys, and click Generate. Each user can have multiple keys. Keys can be revoked at any time without affecting the underlying codes.

Default is 60 requests per minute per API key. Adjust in TiCore/.env (API_RATE_LIMIT).

Yes. Loop POST requests against /api.php. With the default rate limit, ~3,500 codes per hour is sustainable.

Build with QR Track.

Self-host on your server, generate API keys, ship.

Share: 𝕏 Twitter Facebook LinkedIn