API reference
QR codes endpoints
Create and manage dynamic QR codes that redirect to a URL, and list every other code in the account.
- POST
/qr-codesCreate a QR code - GET
/qr-codesList QR codes - GET
/qr-codes/:idRetrieve a QR code - PATCH
/qr-codes/:idUpdate a QR code - DELETE
/qr-codes/:idDelete a QR code
Create a QR code
Creates a dynamic QR code that redirects to a URL you choose.
API key required. Scope: qr:write. Campaign-scoped keys are refused. Plan: Pro, or the Business card plan.
Request
| Header | Required | Value |
|---|---|---|
Authorization | Required | Bearer YOUR_API_KEY. X-API-Key: YOUR_API_KEY is accepted instead. |
Content-Type | Required | application/json |
Idempotency-Key | Optional | Any unique value up to 255 characters. Makes a retry safe. See idempotency. |
Request body
Unknown keys are rejected with 422 on this endpoint.
| Name | Type | Required | Description |
|---|---|---|---|
name | string | Required | Label shown in the dashboard, 1 to 200 characters. |
destinationUrl | string | Required | Where a scan lands. Must be a full http or https URL. Can be changed later. |
shortCode | string | Optional | Custom slug: letters, numbers and hyphens, up to 100 characters. Default: a random 8-character code. |
status | string | Optional | draft marks the code as not yet released. Its short link still resolves for preview until it has been published and then unpublished. One of draft, published. Default: published. |
Example request
curl -X POST "https://api.qrbold.com/api/public/v1/qr-codes" \
-H "Authorization: Bearer $QRBOLD_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"name": "Spring menu",
"destinationUrl": "https://example.com/menu/spring",
"shortCode": "spring-menu"
}'Response
201 The QR code object.
{
"object": "qr_code",
"id": "cmf3k4c2e0003",
"name": "Spring menu",
"type": "url",
"status": "published",
"shortCode": "spring-menu",
"url": "https://qrbold.com/p/spring-menu",
"destinationUrl": "https://example.com/menu/spring",
"paused": false,
"scanCount": 0,
"createdAt": "2026-10-09T09:35:00.000Z",
"updatedAt": "2026-10-09T09:35:00.000Z"
}Errors
| Status | Code | When | Retry? |
|---|---|---|---|
422 | validation_failed | The request body or the query string did not pass validation. | Only after changing the request or the account |
403 | limit_exhausted_products | The account has reached its plan’s QR code limit. | Only after changing the request or the account |
400 | invalid_request | The custom shortCode is already taken. | Only after changing the request or the account |
400 | reserved_short_link | The custom shortCode is a word the platform keeps for itself. | Only after changing the request or the account |
409 | idempotency_key_reused | This Idempotency-Key was already used with a different request. | Only after changing the request or the account |
Every endpoint can also answer 401 invalid_api_key, 403 forbidden, 403 upgrade_required_api, 404 unknown_endpoint, 429 rate limited and 500 internal_error. One failing response is shown below.
{
"error": {
"type": "invalid_request",
"code": "validation_failed",
"message": "One or more fields are invalid.",
"details": [
{
"field": "fields.links.0.type",
"message": "Invalid enum value",
"code": "invalid_enum_value"
},
{
"field": "shortCode",
"message": "Slugs can only contain letters, numbers, and hyphens",
"code": "invalid_string"
}
]
}
}Good to know
- Styling (colours, shapes, logo, frame) is not set through the REST API. A new code starts black on white; design it in the dashboard and the image endpoint returns that design.
Related
List QR codes
Returns every QR code in the account that is not a digital business card, newest first.
API key required. Scope: qr:read. Campaign-scoped keys are refused. Plan: Pro, or the Business card plan.
Request
| Header | Required | Value |
|---|---|---|
Authorization | Required | Bearer YOUR_API_KEY. X-API-Key: YOUR_API_KEY is accepted instead. |
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
limit | integer | Optional | Items per page, 1 to 100. Default: 25. |
offset | integer | Optional | How many items to skip. Default: 0. |
search | string | Optional | Matches part of the name, the slug or the destination URL, ignoring case. |
status | string | Optional | Only codes in this status. Archived codes are left out unless you ask for them. One of draft, published, paused, archived. |
type | string | Optional | Only codes of this type. One of url, file, page, gs1. |
Example request
curl "https://api.qrbold.com/api/public/v1/qr-codes?type=url&limit=25" \
-H "Authorization: Bearer $QRBOLD_API_KEY"Response
200 A list envelope of qr_code objects.
{
"object": "list",
"data": [
{
"object": "qr_code",
"id": "cmf3k4c2e0003",
"name": "Spring menu",
"type": "url",
"status": "published",
"shortCode": "spring-menu",
"url": "https://qrbold.com/p/spring-menu",
"destinationUrl": "https://example.com/menu/spring",
"paused": false,
"scanCount": 0,
"createdAt": "2026-10-09T09:35:00.000Z",
"updatedAt": "2026-10-09T09:35:00.000Z"
}
],
"pagination": {
"total": 1,
"limit": 25,
"offset": 0,
"hasMore": false
}
}Errors
| Status | Code | When | Retry? |
|---|---|---|---|
422 | validation_failed | The request body or the query string did not pass validation. | Only after changing the request or the account |
Every endpoint can also answer 401 invalid_api_key, 403 forbidden, 403 upgrade_required_api, 404 unknown_endpoint, 429 rate limited and 500 internal_error. One failing response is shown below.
{
"error": {
"type": "invalid_request",
"code": "validation_failed",
"message": "One or more fields are invalid.",
"details": [
{
"field": "fields.links.0.type",
"message": "Invalid enum value",
"code": "invalid_enum_value"
},
{
"field": "shortCode",
"message": "Slugs can only contain letters, numbers, and hyphens",
"code": "invalid_string"
}
]
}
}Related
Retrieve a QR code
Returns one QR code by id.
API key required. Scope: qr:read. Campaign-scoped keys are refused. Plan: Pro, or the Business card plan.
Request
| Header | Required | Value |
|---|---|---|
Authorization | Required | Bearer YOUR_API_KEY. X-API-Key: YOUR_API_KEY is accepted instead. |
| Name | Type | Required | Description |
|---|---|---|---|
id | string | Required | The QR code’s id, as returned in the QR code object. |
Example request
curl "https://api.qrbold.com/api/public/v1/qr-codes/cmf3k4c2e0003" \
-H "Authorization: Bearer $QRBOLD_API_KEY"Response
200 The QR code object.
{
"object": "qr_code",
"id": "cmf3k4c2e0003",
"name": "Spring menu",
"type": "url",
"status": "published",
"shortCode": "spring-menu",
"url": "https://qrbold.com/p/spring-menu",
"destinationUrl": "https://example.com/menu/spring",
"paused": false,
"scanCount": 42,
"createdAt": "2026-10-09T09:35:00.000Z",
"updatedAt": "2026-10-09T09:35:00.000Z"
}Errors
| Status | Code | When | Retry? |
|---|---|---|---|
404 | resource_not_found | Nothing with that id exists in this account. | No |
Every endpoint can also answer 401 invalid_api_key, 403 forbidden, 403 upgrade_required_api, 404 unknown_endpoint, 429 rate limited and 500 internal_error. One failing response is shown below.
{
"error": {
"type": "not_found",
"code": "resource_not_found",
"message": "Card not found"
}
}Good to know
- A card id answers 404 here. Cards are read through /cards.
Related
Update a QR code
Renames a code, points it at a new destination, or changes its status.
API key required. Scope: qr:write. Campaign-scoped keys are refused. Plan: Pro, or the Business card plan.
Request
| Header | Required | Value |
|---|---|---|
Authorization | Required | Bearer YOUR_API_KEY. X-API-Key: YOUR_API_KEY is accepted instead. |
Content-Type | Required | application/json |
Idempotency-Key | Optional | Any unique value up to 255 characters. Makes a retry safe. See idempotency. |
| Name | Type | Required | Description |
|---|---|---|---|
id | string | Required | The QR code’s id, as returned in the QR code object. |
Request body
Send at least one field. Fields you leave out are not changed. Unknown keys are rejected with 422.
| Name | Type | Required | Description |
|---|---|---|---|
name | string | Optional | 1 to 200 characters. |
destinationUrl | string | Optional | A full http or https URL. URL codes only; other types answer 422. |
status | string | Optional | paused stops the code redirecting without losing it. archived hides it from the default list. Both are undone by setting published. One of draft, published, paused, archived. |
Example request
curl -X PATCH "https://api.qrbold.com/api/public/v1/qr-codes/cmf3k4c2e0003" \
-H "Authorization: Bearer $QRBOLD_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"destinationUrl": "https://example.com/menu/summer"
}'Response
200 The updated QR code object.
{
"object": "qr_code",
"id": "cmf3k4c2e0003",
"name": "Spring menu",
"type": "url",
"status": "published",
"shortCode": "spring-menu",
"url": "https://qrbold.com/p/spring-menu",
"destinationUrl": "https://example.com/menu/summer",
"paused": false,
"scanCount": 42,
"createdAt": "2026-10-09T09:35:00.000Z",
"updatedAt": "2026-10-09T10:20:00.000Z"
}Errors
| Status | Code | When | Retry? |
|---|---|---|---|
422 | validation_failed | The request body or the query string did not pass validation. | Only after changing the request or the account |
404 | resource_not_found | Nothing with that id exists in this account. | No |
409 | idempotency_key_reused | This Idempotency-Key was already used with a different request. | Only after changing the request or the account |
Every endpoint can also answer 401 invalid_api_key, 403 forbidden, 403 upgrade_required_api, 404 unknown_endpoint, 429 rate limited and 500 internal_error. One failing response is shown below.
{
"error": {
"type": "invalid_request",
"code": "validation_failed",
"message": "One or more fields are invalid.",
"details": [
{
"field": "fields.links.0.type",
"message": "Invalid enum value",
"code": "invalid_enum_value"
},
{
"field": "shortCode",
"message": "Slugs can only contain letters, numbers, and hyphens",
"code": "invalid_string"
}
]
}
}Good to know
- Changing destinationUrl does not change the printed code. That is what makes it dynamic.
Related
Delete a QR code
Moves the code to the account’s Trash. It stops redirecting immediately.
API key required. Scope: qr:write. Campaign-scoped keys are refused. Plan: Pro, or the Business card plan.
Request
| Header | Required | Value |
|---|---|---|
Authorization | Required | Bearer YOUR_API_KEY. X-API-Key: YOUR_API_KEY is accepted instead. |
Idempotency-Key | Optional | Any unique value up to 255 characters. Makes a retry safe. See idempotency. |
| Name | Type | Required | Description |
|---|---|---|---|
id | string | Required | The QR code’s id, as returned in the QR code object. |
Example request
curl -X DELETE "https://api.qrbold.com/api/public/v1/qr-codes/cmf3k4c2e0003" \
-H "Authorization: Bearer $QRBOLD_API_KEY"Response
204 No body.
Errors
| Status | Code | When | Retry? |
|---|---|---|---|
404 | resource_not_found | Nothing with that id exists in this account. | No |
Every endpoint can also answer 401 invalid_api_key, 403 forbidden, 403 upgrade_required_api, 404 unknown_endpoint, 429 rate limited and 500 internal_error. One failing response is shown below.
{
"error": {
"type": "not_found",
"code": "resource_not_found",
"message": "Card not found"
}
}Good to know
- Restorable from Trash in the dashboard. Works for any non-card code, including ones made in the dashboard.