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
| Method | Path | Purpose |
|---|---|---|
| GET | /v1/me | The account a key belongs to, and how many codes it has. |
| GET | /v1/qr-codes | List. Filter by status, limit up to 100. |
| POST | /v1/qr-codes | Create. 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}/scans | Totals, 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.