Developers

API

A REST API over the same service layer the application uses, so anything the interface can do is reachable programmatically — and subject to exactly the same permission checks.

Live. Create a key in your account settings. Every endpoint below is implemented and runs on the same ownership rules as the interface — a key can only ever see and change codes belonging to its own account.

Authentication

A bearer key scoped to one account. Keys are shown once at creation and stored only as a hash, so a leaked key can be revoked but never recovered — there is no “view key” screen, by design. Revoking takes effect on the next request.

Per-key permission scopes and expiry are not implemented: a key currently carries the same rights as the account that made it. Create one key per integration so you can revoke them independently.

curl https://qrc.saiberlab.com/v1/qr-codes \
  -H "Authorization: Bearer mrq_live_..." \
  -H "Idempotency-Key: 7f3c1a9e-..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Autumn menu — table tents",
    "destination": "https://example.com/menu/autumn"
  }'

Creating a code allocates a permanent short link, so a retried request that created a second one would leave an orphan somebody might already have printed. Send an Idempotency-Key and a repeat replays the original response instead, marked Idempotent-Replay: true.

Endpoints

MethodPathPurpose
GET/v1/meThe account a key belongs to, and how many codes it has.
GET/v1/qr-codesList. Filter by status, limit up to 100.
POST/v1/qr-codesCreate. Honours Idempotency-Key.
GET/v1/qr-codes/{id}Fetch one, including its current destination.
PATCH/v1/qr-codes/{id}Repoint, rename, pause or resume. Changes are recorded.
DELETE/v1/qr-codes/{id}Delete permanently. Printed copies stop working.
GET/v1/qr-codes/{id}/scansTotals, by day and by device.

Not built yet

Webhooks, bulk creation and server-side rendering endpoints are designed but not implemented, so they are not documented here as though you could call them. Rendering runs in the browser — the same engine the free generator uses — so an integration that needs image files should render client-side or fetch the code’s short URL and render it itself.

Errors and limits

Errors return a stable machine-readable code alongside a human message; write your handling against the code, never the prose. The limit is 120 requests a minute per key, and the remaining allowance is returned on every response as X-RateLimit-Remaining, so you can back off before being refused rather than after. Asking for a code that belongs to another account returns 404, never 403 — confirming that a record exists would itself leak something.

{ "code": "DESTINATION_REJECTED",
  "message": "That destination resolves to a private network address.",
  "status": 422 }

Building something specific and want to know whether it will fit? Get in touch.