API documentation
Programmatic QR code generation.
Introduction
The QRCraft API exposes a single endpoint at /api/qr.php with two modes:
- Anonymous:
GET /api/qr.php?data=...— returns a PNG image. Nothing is stored. No account needed. - Authenticated: pass a Bearer API key to create, retrieve, and track QR codes tied to your account. Supports all QR types (URL, email, WiFi, vCard, SEPA, Bitcoin, geo, vEvent, text, SMS, phone).
Anonymous endpoint
Encode any string into a QR image. The encoded string is whatever you send — if you want a WiFi QR, format the WiFi string yourself (WIFI:T:WPA;S:MyNet;P:secret;;).
| Parameter | Type | Default | Notes |
|---|---|---|---|
data | string | (required) | Max 2000 chars |
size | integer | 300 | 100–1000 px |
ecc | string | M | L, M, Q, or H |
margin | integer | 4 | 0–10 quiet-zone modules |
format | string | png | png or svg |
Direct embedding:
<img src="https://qrcraft.io/api/qr.php?data=https://example.com&size=400" alt="QR">
Ready-made string formats (copy any of these into ?data=...):
| Use case | String format |
|---|---|
| URL | https://example.com |
| Phone call | tel:+38631123456 |
mailto:info@example.com?subject=Hello&body=Text | |
| SMS | smsto:+38631123456:Prefilled message |
| WiFi | WIFI:T:WPA;S:NetworkName;P:password;; |
| Geo location | geo:46.0569,14.5058 |
| Bitcoin | bitcoin:ADDRESS?amount=0.01 |
| Plain text | Any text you like |
curl examples:
# URL
curl -o qr.png 'https://qrcraft.io/api/qr.php?data=https://example.com'
# WiFi
curl -o wifi.png 'https://qrcraft.io/api/qr.php?data=WIFI:T:WPA;S:GuestNet;P:welcome123;;'
# Phone
curl -o tel.png 'https://qrcraft.io/api/qr.php?data=tel:+38631123456'
# SVG output
curl -o qr.svg 'https://qrcraft.io/api/qr.php?data=hello&format=svg'
HTTP caching (ETag): The anonymous endpoint returns an ETag header and honors If-None-Match — identical requests will return 304 Not Modified without re-generating the image. The response is also marked Cache-Control: public, max-age=86400 so CDNs and browsers cache it for 24 hours.
Authentication
Generate an API key in your profile. The key is shown only once — store it securely. Pass it with every request as either:
- HTTP header:
Authorization: Bearer qrc_...(preferred) - Query parameter:
?key=qrc_...
Invalid or missing keys return 401.
Create a QR code (POST)
POST /api/qr.php with a JSON body:
{
"type": "url",
"name": "My marketing QR",
"fields": { "url": "https://example.com" },
"size": 300,
"ecc": "M",
"margin": 4
}
Fields per type:
url:{ "url": "https://..." }— always created as a dynamic (tracked) QR with a redirect through/r/<token>.email:{ "email": "...", "subject": "...", "body": "..." }sms/phone:{ "phone": "+386...", "message": "..." }wifi:{ "ssid": "...", "password": "...", "encryption": "WPA|WEP|nopass", "hidden": false }vcard:{ "firstname": "...", "lastname": "...", "company": "...", "phone": "...", "email": "...", "website": "..." }sepa:{ "recipient_name": "...", "iban": "...", "bic": "...", "amount": 12.34, "reference": "...", "information": "..." }bitcoin:{ "currency": "bitcoin", "address": "...", "amount": "0.01", "label": "..." }geo:{ "lat": 46.056, "lon": 14.505 }vevent:{ "title": "...", "dtstart": "2026-05-01T10:00", "dtend": "...", "location": "...", "description": "..." }text:{ "content": "..." }
Response (JSON, 201):
{
"id": 123,
"token": "abc123def4",
"type": "url",
"name": "My marketing QR",
"scan_url": "https://qrcraft.io/r/abc123def4",
"image_url": "https://qrcraft.io/api/qr.php?id=123&format=png",
"created_at": "2026-04-18T10:15:00+00:00"
}
For static types (everything except URL), token and scan_url are null.
Add ?format=png or ?format=svg to the POST URL to receive the raw image directly instead of JSON.
Retrieve (GET)
GET /api/qr.php?id=<id> returns the same JSON as the create response. Add &format=png or &format=svg to receive the image. Only QR codes owned by the key's user can be retrieved — others return 404.
Code examples
curl:
curl -X POST https://qrcraft.io/api/qr.php \
-H "Authorization: Bearer qrc_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"type":"url","name":"Promo","fields":{"url":"https://example.com"}}'
JavaScript (fetch):
const res = await fetch('https://qrcraft.io/api/qr.php', {
method: 'POST',
headers: {
'Authorization': 'Bearer qrc_YOUR_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({
type: 'wifi',
name: 'Office WiFi',
fields: { ssid: 'OfficeNet', password: 'secret', encryption: 'WPA' },
}),
});
const data = await res.json();
console.log(data.image_url);
PHP (cURL):
$ch = curl_init('https://qrcraft.io/api/qr.php');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer qrc_YOUR_KEY',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'type' => 'text',
'name' => 'Note',
'fields' => ['content' => 'Hello world'],
]),
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
Errors
| Status | Meaning |
|---|---|
400 | Invalid request (missing/malformed parameters). |
401 | Missing or invalid API key. |
404 | QR code not found or not owned by your key. |
405 | Method not allowed. |
500 | Server error. |
Limits
- Anonymous
dataparameter: max 2000 characters. size: 100–1000 px (default 300).margin: 0–10 modules (default 4).- Maximum 10 API keys per user.