Developers

QR Lift REST API

Create and manage QR codes programmatically. Generate API keys on the Developer page. Download the OpenAPI spec.

Authentication

All endpoints require a Bearer token in the Authorization header.

Authorization: Bearer qrlift_…

List QR codes

GET https://qrlift.codes/api/public/v1/qr?limit=50&offset=0

Create QR code

POST https://qrlift.codes/api/public/v1/qr
Content-Type: application/json

{
  "name": "Summer promo",
  "slug": "summer25",
  "type": "dynamic",
  "kind": "url",
  "target_url": "https://example.com/summer"
}

Get / update / delete

GET    https://qrlift.codes/api/public/v1/qr/{id}
PATCH  https://qrlift.codes/api/public/v1/qr/{id}
DELETE https://qrlift.codes/api/public/v1/qr/{id}

List scans

GET https://qrlift.codes/api/public/v1/qr/{id}/scans?limit=100

Webhooks

Register an endpoint on the Developer page. We POST a JSON body for each event:

POST https://your-app.com/webhook
x-qrlift-event: scan.created
x-qrlift-signature: sha256=<hex>
Content-Type: application/json

{
  "event": "scan.created",
  "sent_at": "2026-06-05T18:00:00.000Z",
  "data": {
    "qr_id": "…",
    "slug": "summer25",
    "scanned_at": "…",
    "country": "US",
    "device": "mobile",
    "os": "iOS",
    "browser": "Safari"
  }
}

Verify the signature with HMAC-SHA256 using your endpoint's signing secret.

// Node.js example
import { createHmac, timingSafeEqual } from "crypto";

function verify(rawBody, signatureHeader, secret) {
  const expected = createHmac("sha256", secret).update(rawBody).digest("hex");
  const got = signatureHeader.replace(/^sha256=/, "");
  return timingSafeEqual(Buffer.from(expected), Buffer.from(got));
}

Errors

{ "error": { "status": 401, "message": "Invalid or revoked API key" } }