REST API

API docs

Programmatic access to QR codes, scan analytics, and workspace metadata. Authenticate with an API key from the API Keys page. Machine-readable OpenAPI 3.1 spec is available at /openapi.json.

Authentication

All requests need a Bearer token in the Authorization header. Generate keys from the API Keys page; the raw key is shown once at creation, then only the prefix is visible. Keys are scoped to a single workspace.

Authorization: Bearer qrf_live_...

Rate limits

Per-workspace per-minute limits (shared across all of a workspace's keys). Every response carries the headers below; exceeding the limit returns HTTP 429 with a Retry-After header (seconds until the window resets).

  • Free — 60 req/min
  • Pro — 300 req/min
  • Business — 1,000 req/min
X-RateLimit-Plan: pro
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 297
X-RateLimit-Reset: 1718724000

# When exceeded:
HTTP/1.1 429 Too Many Requests
Retry-After: 42

API reference

Base URLhttps://www.qra.cc/api/v1
GET/qr

Paginated list of QR codes in your workspace.

Parameters

NameInTypeDescription
pagequeryinteger · default 1
limitqueryinteger · default 20

Request

curl -X GET "https://www.qra.cc/api/v1/qr?page=1&limit=20" \
  -H "Authorization: Bearer qrf_live_..."

Example response 200

{
  "data": [
    {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "slug": "abc123xyz",
      "name": "Riyadh Mall — counter sticker",
      "type": "url",
      "destination": "https://example.com/menu",
      "status": "active",
      "created_at": "2026-04-01T12:00:00Z",
      "updated_at": "2026-04-01T12:00:00Z"
    }
  ],
  "pagination": {
    "page": 0,
    "limit": 0,
    "total": 0,
    "pages": 0
  }
}

Responses

  • 200Paginated list
  • 401Missing or invalid API key
  • 429Rate limit exceeded — too many requests this minute (limit is per workspace).
POST/qr

Create a new dynamic QR code — subject to your plan’s code-count limit.

Request body application/json

FieldTypeDescription
name*string · e.g. Q4 catalogue insert
typestring
destinationstring · e.g. https://example.com/catalogue

Request

curl -X POST "https://www.qra.cc/api/v1/qr" \
  -H "Authorization: Bearer qrf_live_..." \
  -H "Content-Type: application/json" \
  -d '{"name":"Q4 catalogue insert","type":"url","destination":"https://example.com/catalogue"}'

Example response 201

{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "slug": "abc123xyz",
  "name": "Riyadh Mall — counter sticker",
  "type": "url",
  "destination": "https://example.com/menu",
  "status": "active",
  "created_at": "2026-04-01T12:00:00Z",
  "updated_at": "2026-04-01T12:00:00Z"
}

Responses

  • 201Created
  • 400Validation error
  • 403Plan limit reached
  • 429Rate limit exceeded — too many requests this minute (limit is per workspace).
GET/qr/{id}

Fetch a single QR code by its id.

Parameters

NameInTypeDescription
id*pathstring (uuid)

Request

curl -X GET "https://www.qra.cc/api/v1/qr/{id}" \
  -H "Authorization: Bearer qrf_live_..."

Example response 200

{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "slug": "abc123xyz",
  "name": "Riyadh Mall — counter sticker",
  "type": "url",
  "destination": "https://example.com/menu",
  "status": "active",
  "created_at": "2026-04-01T12:00:00Z",
  "updated_at": "2026-04-01T12:00:00Z"
}

Responses

  • 200Found
  • 404Not found
  • 429Rate limit exceeded — too many requests this minute (limit is per workspace).
PATCH/qr/{id}

Update a QR code’s name, destination, or status (active / paused / expired).

Parameters

NameInTypeDescription
id*pathstring (uuid)

Request body application/json

FieldTypeDescription
namestring
destinationstring
statusstring · active · paused · expired

Request

curl -X PATCH "https://www.qra.cc/api/v1/qr/{id}" \
  -H "Authorization: Bearer qrf_live_..." \
  -H "Content-Type: application/json" \
  -d '{"name":"string","destination":"string","status":"active"}'

Example response 200

{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "slug": "abc123xyz",
  "name": "Riyadh Mall — counter sticker",
  "type": "url",
  "destination": "https://example.com/menu",
  "status": "active",
  "created_at": "2026-04-01T12:00:00Z",
  "updated_at": "2026-04-01T12:00:00Z"
}

Responses

  • 200Updated
  • 429Rate limit exceeded — too many requests this minute (limit is per workspace).
DELETE/qr/{id}

Permanently delete a QR code and all of its scans.

Parameters

NameInTypeDescription
id*pathstring (uuid)

Request

curl -X DELETE "https://www.qra.cc/api/v1/qr/{id}" \
  -H "Authorization: Bearer qrf_live_..."

Responses

  • 204Deleted
  • 429Rate limit exceeded — too many requests this minute (limit is per workspace).
GET/qr/{id}/scans

Raw per-scan log — timestamp, country, device, OS, browser, referrer. Filter with since / until.

Parameters

NameInTypeDescription
id*pathstring (uuid)
pagequeryinteger · default 1
limitqueryinteger · default 50
sincequerystring (date-time)
untilquerystring (date-time)

Request

curl -X GET "https://www.qra.cc/api/v1/qr/{id}/scans?page=1&limit=50" \
  -H "Authorization: Bearer qrf_live_..."

Example response 200

{
  "data": [
    {
      "id": 0,
      "ts": "2026-04-01T12:00:00Z",
      "country": "SA",
      "city": "Riyadh",
      "device": "mobile",
      "os": "iOS",
      "browser": "Safari",
      "referrer": "string"
    }
  ],
  "pagination": {
    "page": 0,
    "limit": 0,
    "total": 0,
    "pages": 0
  }
}

Responses

  • 200Paginated scans
  • 429Rate limit exceeded — too many requests this minute (limit is per workspace).