Integrate QRflex into your system
Full REST API, webhooks and ready-made connectors. Automate QR code creation, track scans and connect QRflex with the tools you already use.
What you can do with the API and webhooks
You don't have to be a developer. Most scenarios can be done with a few lines of code, or none at all via Zapier and Make.
Automated QR creation
Generate QR codes programmatically from your order system, CRM or e-shop.
Campaign redirects
Change the QR target on the fly and track which campaign drove how many scans.
Real-time notifications
Webhooks notify your system instantly on every scan or code change.
Bulk operations
Import or export thousands of codes at once via the batch API.
Ready-made integrations
Connect QRflex to the tools you already use. Just log in and pick what should happen.
Zapier
Connect to 6,000+ apps without a single line of code.
Make (Integromat)
Visual automation with conditions and branching.
Slack
Notifications to a channel on new scans or limit exceeded.
Google Analytics 4
Pass UTM parameters directly to GA4 without extra setup.
Google Sheets
Auto-export scan statistics to a spreadsheet.
Custom webhook
Any HTTP endpoint — your server, your rules.
First request in five minutes
-
1
Create an API key
In account settings, generate a key and assign the permissions you need (read, write or both).
-
2
Send a request
Add the Authorization: Bearer <your-key> header and POST to /api/v1/qr-codes.
-
3
Check the response
The API returns 201 Created with the URL of the new code and its ID for further operations.
curl -X POST https://qrflex.io/api/v1/qr-codes \
-H "Authorization: Bearer qrf_your_key" \
-H "Content-Type: application/json" \
-d '{"type":"url","target":"https://example.com","name":"My QR"}'
$ch = curl_init('https://qrflex.io/api/v1/qr-codes');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer qrf_your_key',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'type' => 'url',
'target' => 'https://example.com',
'name' => 'My QR',
]),
CURLOPT_RETURNTRANSFER => true,
]);
$response = curl_exec($ch);
const response = await fetch('https://qrflex.io/api/v1/qr-codes', {
method: 'POST',
headers: {
'Authorization': 'Bearer qrf_your_key',
'Content-Type': 'application/json',
},
body: JSON.stringify({
type: 'url',
target: 'https://example.com',
name: 'My QR',
}),
});
const data = await response.json();
import requests
response = requests.post(
'https://qrflex.io/api/v1/qr-codes',
headers={
'Authorization': 'Bearer qrf_your_key',
'Content-Type': 'application/json',
},
json={
'type': 'url',
'target': 'https://example.com',
'name': 'My QR',
},
)
data = response.json()
What the API can do
All paths start with /api/v1
| Group | Methods | Description |
|---|---|---|
/qr-codes |
GET POST PATCH DELETE | QR codes — Create, read, update and delete dynamic QR codes. |
/campaigns |
GET POST PATCH | Campaigns — Manage marketing campaigns and their UTM parameters. |
/scans |
GET | Scan statistics — Aggregated and detailed scan data (time, location, device). |
/webhooks |
GET POST DELETE | Webhooks — Register and manage webhook endpoints. |
/api-keys |
GET POST DELETE | API keys — Create, list and revoke API keys. |
/workspace |
GET | Workspace — Read workspace info and its limits. |
/export |
GET | Export — Bulk export of codes and statistics in CSV or JSON format. |
Events arrive on their own
Give us the URL to send messages to and choose which events to subscribe to. Every message is signed (HMAC-SHA256, Standard Webhooks) and we retry on server failure.
Verify the signature in the webhook-signature header; detect duplicates using webhook-id.
{
"id": "msg_01xyz",
"type": "qr_code.scanned",
"timestamp": "2026-09-25T14:23:10Z",
"data": {
"qr_code_id": "qr_abc123",
"scan_id": "scan_def456",
"target": "https://example.com",
"location": {
"country": "CZ",
"city": "Praha"
},
"device": "mobile"
}
}
Predictable behaviour on every endpoint
Same rules for auth, pagination, errors and rate limits. Write the integration once.
Bearer token
Every request carries an Authorization: Bearer header.
Authorization: Bearer qrf_...
Pagination
Results are paginated via cursor. Maximum 100 items per page.
?limit=50&cursor=eyJpZCI6...
HTTP status codes
Standard codes: 200 OK, 201 Created, 400 Bad Request, 401 Unauthorized, 429 Too Many Requests.
HTTP 429 Too Many Requests
Rate limiting
Limit of 1,000 requests per minute per API key. X-RateLimit-* headers tell you the remaining count.
X-RateLimit-Remaining: 843
JSON everywhere
Requests and responses are always application/json (or application/problem+json for errors).
Content-Type: application/json
Idempotent requests
GET and DELETE are idempotent. For PUT: same data = same result.
Idempotency-Key: uuid-v4
Meaningful errors
Errors come in the standard application/problem+json format. The description is in your language and for validation errors you will see which field is wrong.
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
"title": "Validation failed",
"status": 400,
"detail": "Pole target je povinné.",
"violations": [
{
"field": "target",
"message": "Toto pole nesmí být prázdné."
}
]
}
Keys and data under control
Scoped API keys
Each key has only the permissions you assign. Read, write or both separately.
Key revocation
Invalidate a compromised key with a single click without affecting other keys.
HTTPS everywhere
All communication is exclusively over TLS 1.2+. HTTP requests are redirected.
Data in the EU
Servers located in Germany (Frankfurt). Your data never leaves the European Union.
Need help with integration?
Complete reference with examples in curl, PHP, JavaScript and Python. Or write to us.