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;;).

ParameterTypeDefaultNotes
datastring(required)Max 2000 chars
sizeinteger300100–1000 px
eccstringML, M, Q, or H
margininteger40–10 quiet-zone modules
formatstringpngpng 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 caseString format
URLhttps://example.com
Phone calltel:+38631123456
Emailmailto:info@example.com?subject=Hello&body=Text
SMSsmsto:+38631123456:Prefilled message
WiFiWIFI:T:WPA;S:NetworkName;P:password;;
Geo locationgeo:46.0569,14.5058
Bitcoinbitcoin:ADDRESS?amount=0.01
Plain textAny 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

StatusMeaning
400Invalid request (missing/malformed parameters).
401Missing or invalid API key.
404QR code not found or not owned by your key.
405Method not allowed.
500Server error.

Limits

  • Anonymous data parameter: max 2000 characters.
  • size: 100–1000 px (default 300).
  • margin: 0–10 modules (default 4).
  • Maximum 10 API keys per user.