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
TiCore/.env (API_RATE_LIMIT)./api.php. With the default rate limit, ~3,500 codes per hour is sustainable.