API reference
Create and manage dynamic QR codes and short links. Available on the Pro plan.
Base URL https://ctrlshiftqr.com/api/v1 · OpenAPI 3.1 spec
Authentication
Create a key in Settings → API keys (Pro plan) and send it as a bearer token. Keys are shown once; store them securely and never in client-side code. Keys stop working if the account leaves the Pro plan.
curl https://ctrlshiftqr.com/api/v1/qr-codes \ -H "Authorization: Bearer csqr_your_key"
Errors & rate limits
Errors use HTTP status codes with a JSON body. Field validation errors include details.fieldErrors. Each key may make 60 requests per minute; responses carry X-RateLimit-Limit and X-RateLimit-Remaining, and 429 responses include Retry-After.
{ "error": { "code": "limit_reached", "message": "You've reached the plan limit…" } }Pagination
List endpoints return { data, nextCursor }. Pass ?cursor=<nextCursor> to get the next page (newest first, up to 100 per page).
/qr-codesList QR codes
| Query parameter | Type | Description |
|---|---|---|
| limit | integer (default 25) | |
| cursor | string | `nextCursor` from the previous page. |
| q | string | Search by name, destination or slug. |
curl -X GET https://ctrlshiftqr.com/api/v1/qr-codes \ -H "Authorization: Bearer csqr_your_key"
Responses: 200, 400, 401, 403, 429
/qr-codesCreate a QR code
`type` defaults to `URL` (dynamic: the image encodes a CtrlShiftQR redirect, so `destination` can change later). Other types are static and take a `payload`.
curl -X POST https://ctrlshiftqr.com/api/v1/qr-codes \
-H "Authorization: Bearer csqr_your_key" \
-H "Content-Type: application/json" \
-d '{"name":"Spring menu","destination":"https://example.com/menu","style":{"fgColor":"#111111","dotStyle":"rounded"}}'Responses: 201, 400, 401, 403, 429
/qr-codes/{id}Get a QR code
curl -X GET https://ctrlshiftqr.com/api/v1/qr-codes/ID \ -H "Authorization: Bearer csqr_your_key"
Responses: 200, 400, 401, 403, 429
/qr-codes/{id}Update a QR code
Changing `destination` never changes a dynamic code's image.
curl -X PATCH https://ctrlshiftqr.com/api/v1/qr-codes/ID \
-H "Authorization: Bearer csqr_your_key" \
-H "Content-Type: application/json" \
-d '{"destination":"https://example.com/summer-menu"}'Responses: 200, 400, 401, 403, 429
/qr-codes/{id}Delete a QR code
curl -X DELETE https://ctrlshiftqr.com/api/v1/qr-codes/ID \ -H "Authorization: Bearer csqr_your_key"
Responses: 204, 400, 401, 403, 429
/qr-codes/{id}/imageRender the QR image
| Query parameter | Type | Description |
|---|---|---|
| format | png | svg (default png) | |
| size | integer (default 512) |
curl -X GET https://ctrlshiftqr.com/api/v1/qr-codes/ID/image \ -H "Authorization: Bearer csqr_your_key"
Responses: 200, 400, 401, 403, 429
/linksList short links
| Query parameter | Type | Description |
|---|---|---|
| limit | integer (default 25) | |
| cursor | string | `nextCursor` from the previous page. |
| q | string | Search by name, destination or slug. |
curl -X GET https://ctrlshiftqr.com/api/v1/links \ -H "Authorization: Bearer csqr_your_key"
Responses: 200, 400, 401, 403, 429
/linksCreate a short link
curl -X POST https://ctrlshiftqr.com/api/v1/links \
-H "Authorization: Bearer csqr_your_key" \
-H "Content-Type: application/json" \
-d '{"destination":"https://example.com/launch","slug":"launch"}'Responses: 201, 400, 401, 403, 409, 429
/links/{id}Get a short link
curl -X GET https://ctrlshiftqr.com/api/v1/links/ID \ -H "Authorization: Bearer csqr_your_key"
Responses: 200, 400, 401, 403, 429
/links/{id}Update a short link
curl -X PATCH https://ctrlshiftqr.com/api/v1/links/ID \
-H "Authorization: Bearer csqr_your_key" \
-H "Content-Type: application/json" \
-d '{"destination":"https://example.com/new"}'Responses: 200, 400, 401, 403, 429
/links/{id}Delete a short link
curl -X DELETE https://ctrlshiftqr.com/api/v1/links/ID \ -H "Authorization: Bearer csqr_your_key"
Responses: 204, 400, 401, 403, 429
/analyticsScan analytics
| Query parameter | Type | Description |
|---|---|---|
| range | 7d | 30d | 90d | 365d (default 30d) | |
| tz | string (default UTC) | IANA time zone for day buckets. |
| qr | string | Limit to one QR code id. |
| link | string | Limit to one short link id. |
curl -X GET https://ctrlshiftqr.com/api/v1/analytics \ -H "Authorization: Bearer csqr_your_key"
Responses: 200, 400, 401, 403, 429
/meCurrent plan, limits and usage
curl -X GET https://ctrlshiftqr.com/api/v1/me \ -H "Authorization: Bearer csqr_your_key"
Responses: 200, 400, 401, 403, 429