Developers

API reference

REST API v1 — manage QR codes and pull analytics with cue_live_* bearer keys.

The Cue API is a small REST API over JSON. Create a key in Dashboard → API; keys look like cue_live_a1b2c3... and are sent as a bearer token. Every request is made against your API base URL — https://grandiose-alpaca-668.convex.site — which is also shown alongside your keys in the dashboard. API access is included on Business and Enterprise plans.

Authentication
curl https://grandiose-alpaca-668.convex.site/api/v1/qrcodes \
  -H "Authorization: Bearer cue_live_a1b2c3d4e5f6"

List QR codes

GET /api/v1/qrcodes returns your 100 most recent codes, newest first. createdAt is a Unix timestamp in milliseconds.

GET /api/v1/qrcodes → 200
{
  "data": [
    {
      "id": "jd7f2k9qmx04v5gz1nwe8c3ht",
      "name": "Spring menu — window sticker",
      "kind": "dynamic",
      "status": "active",
      "shortCode": "x7Kp2q",
      "shortUrl": "https://scancue.co/r/x7Kp2q",
      "destination": "https://example.com/menu/spring",
      "scans": 1284,
      "uniqueScans": 1102,
      "createdAt": 1746177240000
    }
  ]
}

Create a QR code

POST /api/v1/qrcodes creates a dynamic code from a name and a destination URL, and returns a ready-to-encode short URL. Both fields are required, and the URL must be http(s). Codes created by API start with the default style — open them in the designer to restyle; the short URL never changes.

POST /api/v1/qrcodes → 201
curl -X POST https://grandiose-alpaca-668.convex.site/api/v1/qrcodes \
  -H "Authorization: Bearer cue_live_a1b2c3d4e5f6" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Summer campaign — poster A",
    "url": "https://example.com/summer"
  }'

{
  "data": {
    "id": "jd7f2k9qmx04v5gz1nwe8c3ht",
    "shortCode": "x7Kp2q",
    "shortUrl": "https://scancue.co/r/x7Kp2q"
  }
}

Update a destination

PATCH /api/v1/qrcodes/:id/destination repoints a dynamic code atomically and returns the new destination version. The change takes effect within seconds; printed codes keep working throughout.

PATCH /api/v1/qrcodes/:id/destination → 200
curl -X PATCH https://grandiose-alpaca-668.convex.site/api/v1/qrcodes/jd7f2k9qmx04v5gz1nwe8c3ht/destination \
  -H "Authorization: Bearer cue_live_a1b2c3d4e5f6" \
  -H "Content-Type: application/json" \
  -d '{ "url": "https://example.com/menu/summer" }'

{
  "data": {
    "id": "jd7f2k9qmx04v5gz1nwe8c3ht",
    "destination": "https://example.com/menu/summer",
    "version": 2
  }
}

Analytics

GET /api/v1/analytics returns daily scan aggregates. Scope to one code with ?qrcodeId= (omit it for the whole workspace) and set the window with ?from= and ?to= as YYYY-MM-DD dates — the default is the last 30 days.

GET /api/v1/analytics?qrcodeId=jd7f2k9q...&from=2026-06-01&to=2026-06-07 → 200
{
  "data": {
    "totalScans": 403,
    "uniqueScans": 352,
    "days": [
      { "day": "2026-06-01", "total": 214, "uniques": 187 },
      { "day": "2026-06-02", "total": 189, "uniques": 165 }
    ]
  }
}

Errors and limits

Errors use conventional status codes with a plain JSON body: { "error": "name and url are required" }. You'll see 400 for invalid input, 401 for a missing or revoked key, 402 when a plan limit blocks the request, 404 for codes outside your workspace, and 429 once you exceed the rate limit of 120 requests per minute per key.