QR code API
Create codes from your own backend, read their scans, and receive a webhook the moment somebody scans one. This page needs no account.
The API is part of the Business plan. Keys are created in the dashboard under API & webhooks, and are shown once — a lost key is revoked and replaced, never recovered.
Base URL
https://enqre.com/api/v1Authentication
Every request carries the key as a bearer token. A request without a valid key gets 401; a valid key on a plan without the API gets 403.
curl https://enqre.com/api/v1/qrcodes \
-H "Authorization: Bearer $ENQRE_API_KEY"Endpoints
GET/api/v1/qrcodes?limit=50&cursor=<id>
List your codes, newest first. Cursor pagination: pass the returned nextCursor to get the next page.
{
"data": [
{
"id": "clx…", "name": "Table tent", "type": "URL",
"slug": "a1b2c3", "destinationUrl": "https://example.com/menu",
"scanCount": 128, "active": true, "createdAt": "2026-09-01T10:00:00.000Z",
"shortUrl": "https://enqre.com/r/a1b2c3"
}
],
"nextCursor": "clx…"
}POST/api/v1/qrcodes
Create a dynamic URL code. The response carries the short URL to print.
{ "name": "Table tent", "url": "https://example.com/menu" }201 Created
{
"data": {
"id": "clx…", "name": "Table tent", "slug": "a1b2c3",
"destinationUrl": "https://example.com/menu",
"shortUrl": "https://enqre.com/r/a1b2c3"
}
}GET/api/v1/qrcodes/{id}
Read one code.
PATCH/api/v1/qrcodes/{id}
Change a code — including its destination. This is the whole point of a dynamic code: the printed copy keeps working and starts pointing somewhere else.
{ "url": "https://example.com/autumn-menu", "name": "Autumn menu", "active": true }DELETE/api/v1/qrcodes/{id}
Delete a code. Printed copies stop resolving, so this is not the way to pause a campaign — set active to false instead.
GET/api/v1/qrcodes/{id}/scans
The last 1,000 scans of one code, newest first, plus the lifetime total.
{
"total": 128,
"data": [
{ "createdAt": "2026-09-06T18:12:03.000Z", "device": "mobile", "os": "iOS", "browser": "Safari" }
]
}Errors
Errors are JSON with a stable machine-readable code. Branch on the code, not on the message — messages may be reworded, codes will not.
| 401 | invalid_api_key | No key, a revoked key, or one that does not exist. |
| 403 | api_not_available_on_plan | The key is valid; the account is not on Business. |
| 400 | invalid_body | The JSON body failed validation. |
| 402 | plan_limit_reached | The account is at its dynamic-code limit. |
| 404 | not_found | No code with that id on this account. |
| 429 | rate_limited | More than 60 writes in a minute. |
Rate limit
60 writes per minute per account, answered with 429 when exceeded. Reads are not limited today; that is not a promise to build on.
Webhooks
Register a URL under API & webhooks and every scan is posted to it as it happens, so your own system hears about a scan without polling for it.
POST your-endpoint
X-Enqre-Event: scan.created
X-Enqre-Signature: <hex hmac-sha256 of the raw body>
Content-Type: application/json
{
"event": "scan.created",
"qrCodeId": "clx…",
"slug": "a1b2c3",
"name": "Table tent",
"device": "mobile",
"os": "iOS",
"browser": "Safari"
}Verify the signature
Compute HMAC-SHA256 of the raw request body with your webhook secret and compare it to the header. Reject anything that does not match — and compare in constant time.
import crypto from "node:crypto";
const raw = await req.text(); // the raw body, before JSON.parse
const expected = crypto
.createHmac("sha256", process.env.ENQRE_WEBHOOK_SECRET)
.update(raw)
.digest("hex");
const given = req.headers.get("x-enqre-signature") ?? "";
const ok =
given.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(given), Buffer.from(expected));Postman collection
Every endpoint on this page, ready to run: import the collection, set the apiKey variable, send.
Download the collectionWhat the API does not do yet
Codes created through the API are URL codes with the default design. The other sixteen types, the design fields and bulk import are dashboard-only for now. Everything the API does create is a normal code: editable, measurable and printable like any other.
Get a key
The API, webhooks, GS1 Digital Link, white-label and your own domain are on Business, €39 a month.
See the plans