API Reference
QRlumo exposes a REST API for creating and managing QR codes, reading scan analytics, and automating workflows. The API is designed for teams who want to embed QR code management into their own systems — CRMs, ERPs, print pipelines, or marketing automation.
Base URL
https://api.qrlumo.com/v1
Authentication
All requests require a Bearer token in the Authorization header. Generate API keys under Workspace → Settings → API Keys.
curl https://api.qrlumo.com/v1/workspaces \
-H "Authorization: Bearer qrl_live_..."
API keys are scoped to a workspace. Keys with read scope can only fetch data; write scope allows mutations.
QR Codes
Create a QR code
POST /workspaces/{workspaceId}/qrcodes
Request body
{
"name": "spring_packaging",
"type": "dynamic",
"content": {
"url": "https://brand.com/spring-offer"
},
"projectId": "proj_abc123"
}
| Field | Type | Required | Description |
|---|---|---|---|
name | string | ✓ | Human-readable label |
type | static | dynamic | ✓ | Code type |
content.url | string | ✓ | Destination URL |
projectId | string | Assign to a project folder |
Response
{
"id": "qr_xyz789",
"name": "spring_packaging",
"type": "dynamic",
"shortUrl": "https://qrlu.mo/r/abc",
"content": { "url": "https://brand.com/spring-offer" },
"scans": 0,
"createdAt": "2026-06-10T09:00:00Z"
}
Update destination
PATCH /workspaces/{workspaceId}/qrcodes/{qrcodeId}
{
"content": {
"url": "https://brand.com/summer-campaign"
}
}
Only dynamic codes support destination updates. Static codes return 400.
List QR codes
GET /workspaces/{workspaceId}/qrcodes?page=1&limit=50&projectId=proj_abc
Delete a QR code
DELETE /workspaces/{workspaceId}/qrcodes/{qrcodeId}
Deleting a dynamic code makes its short URL return 404. Deleting a static code has no effect on already-printed patterns (they encode the URL directly).
Scan Analytics
Get scan stats
GET /workspaces/{workspaceId}/qrcodes/{qrcodeId}/stats?from=2026-06-01&to=2026-06-30
Response
{
"total": 2847,
"unique": 1923,
"byDay": [
{ "date": "2026-06-01", "scans": 142, "unique": 98 },
...
],
"byCountry": [
{ "country": "CN", "scans": 1204 },
{ "country": "US", "scans": 441 }
],
"byDevice": [
{ "device": "iOS", "scans": 1589 },
{ "device": "Android", "scans": 891 }
]
}
Raw scan events
GET /workspaces/{workspaceId}/qrcodes/{qrcodeId}/events?cursor=&limit=100
Returns paginated raw scan events. Available on Team and Business plans.
Workspaces
List workspaces
GET /workspaces
Get workspace
GET /workspaces/{workspaceId}
Rate limits
| Plan | Requests / min | Requests / month |
|---|---|---|
| Free | 10 | — |
| Pro | 60 | — |
| Team | 120 | 20,000 |
| Business | 300 | 200,000 |
Exceeding the rate limit returns 429 Too Many Requests.
Error format
All errors follow a consistent JSON shape:
{
"error": {
"code": "qr_not_found",
"message": "QR code qr_xyz789 does not exist in this workspace.",
"status": 404
}
}
Client libraries
Official SDKs are in progress. In the meantime, the REST API works with any HTTP client.
// TypeScript — no SDK needed
const res = await fetch(
`https://api.qrlumo.com/v1/workspaces/${workspaceId}/qrcodes`,
{
method: 'POST',
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: 'my_code',
type: 'dynamic',
content: { url: 'https://example.com' },
}),
}
);
const code = await res.json();
Planned SDK languages: TypeScript/Node.js · Python · Go · PHP
Join the SDK waitlist to be notified when your language is ready.
OpenAPI spec
The full OpenAPI 3.0 spec is available at:
https://api.qrlumo.com/openapi.json
Use it to generate a typed client in any language with openapi-generator or oapi-codegen.