API reference
Digital business cards endpoints
Create, read, update and delete digital business cards.
- POST
/cardsCreate a card - GET
/cardsList cards - GET
/cards/:idRetrieve a card - PATCH
/cards/:idUpdate a card - DELETE
/cards/:idDelete a card - GET
/cards/:id/walletGet wallet links
Create a card
Creates one digital business card and returns it, including its public URL.
API key required. Scope: cards: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 dropped without an error on this endpoint, both at the top level and inside fields. A misspelled field name therefore creates a card without that value: compare the fields in the response with what you sent.
| Name | Type | Required | Description |
|---|---|---|---|
fields | object | Optional | The person’s data. See the card fields table. Defaults to an empty object, but a template may require some fields. |
name | string | Optional | Label shown in the dashboard, 1 to 200 characters. Default: first + last name. |
templateId | string | Optional | Copies this template’s design onto the card and applies its field rules. Default: the default starter design. |
shortCode | string | Optional | Custom slug for the public URL: letters, numbers and hyphens, up to 100 characters. Default: a random 8-character code. |
status | string | Optional | published marks the card live straight away. draft marks it as not yet released, but its URL still opens for preview, so do not treat a draft as private. One of draft, published. Default: published. |
Example request
curl -X POST "https://api.qrbold.com/api/public/v1/cards" \
-H "Authorization: Bearer $QRBOLD_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"name": "Ada Lovelace",
"templateId": "cmf3k1p7d0002",
"shortCode": "ada-lovelace",
"status": "published",
"fields": {
"firstName": "Ada",
"lastName": "Lovelace",
"title": "Head of Engineering",
"company": "Analytical Engines Ltd",
"photoUrl": "https://example.com/photos/ada.jpg",
"companyLogoUrl": "https://example.com/brand/logo.png",
"bio": "Builds calculating machines and the teams around them.",
"emails": [
{
"label": "Work",
"value": "ada@example.com"
}
],
"phones": [
{
"label": "Mobile",
"value": "+44 20 7946 0958"
}
],
"links": [
{
"type": "website",
"url": "example.com"
},
{
"type": "linkedin",
"url": "linkedin.com/in/ada-lovelace"
}
],
"address": {
"city": "London",
"country": "United Kingdom"
}
}
}'Response
201 The card object.
{
"object": "card",
"id": "cmf3k2a9x0001",
"name": "Ada Lovelace",
"shortCode": "ada-lovelace",
"status": "published",
"url": "https://qrbold.com/c/ada-lovelace",
"vcardUrl": "https://qrbold.com/c/ada-lovelace/vcard",
"templateId": "cmf3k1p7d0002",
"externalId": null,
"paused": false,
"fields": {
"firstName": "Ada",
"lastName": "Lovelace",
"title": "Head of Engineering",
"company": "Analytical Engines Ltd",
"photoUrl": "https://example.com/photos/ada.jpg",
"companyLogoUrl": "https://example.com/brand/logo.png",
"bio": "Builds calculating machines and the teams around them.",
"emails": [
{
"label": "Work",
"value": "ada@example.com"
}
],
"phones": [
{
"label": "Mobile",
"value": "+44 20 7946 0958"
}
],
"links": [
{
"type": "website",
"url": "example.com"
},
{
"type": "linkedin",
"url": "linkedin.com/in/ada-lovelace"
}
],
"address": {
"city": "London",
"country": "United Kingdom"
}
},
"createdAt": "2026-10-09T09:30:00.000Z",
"updatedAt": "2026-10-09T09:30: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 |
422 | validation_failed | The card’s template does not allow what was sent. | Only after changing the request or the account |
403 | limit_exhausted_cards | The account has used every card its plan covers. | 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 |
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
- The template’s design is copied onto the card when it is created. Editing the template later does not change cards that already exist.
- Check paused in the response before printing a QR code: a paused card exists but its URL does not open.
Related
List cards
Returns the account’s cards, newest first, one page at a time.
API key required. Scope: cards: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 card’s name, ignoring case. Up to 200 characters. |
templateId | string | Optional | Only cards created from this template. |
status | string | Optional | Only cards in this status. Archived cards are left out unless you ask for them. One of draft, published, paused, archived. |
Example request
curl "https://api.qrbold.com/api/public/v1/cards?limit=25&offset=0" \
-H "Authorization: Bearer $QRBOLD_API_KEY"Response
200 A list envelope of card objects.
{
"object": "list",
"data": [
{
"object": "card",
"id": "cmf3k2a9x0001",
"name": "Ada Lovelace",
"shortCode": "ada-lovelace",
"status": "published",
"url": "https://qrbold.com/c/ada-lovelace",
"vcardUrl": "https://qrbold.com/c/ada-lovelace/vcard",
"templateId": "cmf3k1p7d0002",
"externalId": null,
"paused": false,
"fields": {
"firstName": "Ada",
"lastName": "Lovelace",
"title": "Head of Engineering",
"company": "Analytical Engines Ltd",
"photoUrl": "https://example.com/photos/ada.jpg",
"companyLogoUrl": "https://example.com/brand/logo.png",
"bio": "Builds calculating machines and the teams around them.",
"emails": [
{
"label": "Work",
"value": "ada@example.com"
}
],
"phones": [
{
"label": "Mobile",
"value": "+44 20 7946 0958"
}
],
"links": [
{
"type": "website",
"url": "example.com"
},
{
"type": "linkedin",
"url": "linkedin.com/in/ada-lovelace"
}
],
"address": {
"city": "London",
"country": "United Kingdom"
}
},
"createdAt": "2026-10-09T09:30:00.000Z",
"updatedAt": "2026-10-09T09:30: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 card
Returns one card by id.
API key required. Scope: cards: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 card’s id, as returned in the card object. |
Example request
curl "https://api.qrbold.com/api/public/v1/cards/cmf3k2a9x0001" \
-H "Authorization: Bearer $QRBOLD_API_KEY"Response
200 The card object.
{
"object": "card",
"id": "cmf3k2a9x0001",
"name": "Ada Lovelace",
"shortCode": "ada-lovelace",
"status": "published",
"url": "https://qrbold.com/c/ada-lovelace",
"vcardUrl": "https://qrbold.com/c/ada-lovelace/vcard",
"templateId": "cmf3k1p7d0002",
"externalId": null,
"paused": false,
"fields": {
"firstName": "Ada",
"lastName": "Lovelace",
"title": "Head of Engineering",
"company": "Analytical Engines Ltd",
"photoUrl": "https://example.com/photos/ada.jpg",
"companyLogoUrl": "https://example.com/brand/logo.png",
"bio": "Builds calculating machines and the teams around them.",
"emails": [
{
"label": "Work",
"value": "ada@example.com"
}
],
"phones": [
{
"label": "Mobile",
"value": "+44 20 7946 0958"
}
],
"links": [
{
"type": "website",
"url": "example.com"
},
{
"type": "linkedin",
"url": "linkedin.com/in/ada-lovelace"
}
],
"address": {
"city": "London",
"country": "United Kingdom"
}
},
"createdAt": "2026-10-09T09:30:00.000Z",
"updatedAt": "2026-10-09T09:30: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"
}
}Related
Update a card
Replaces the card’s data, and optionally moves it to another template.
API key required. Scope: cards: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 card’s id, as returned in the card object. |
Request body
Only fields and templateId are accepted: any other top-level key is rejected with 422. The card’s name follows the person’s name automatically. The design, status and short code cannot be changed here.
| Name | Type | Required | Description |
|---|---|---|---|
fields | object | Required | The card’s complete data. Scalar fields you leave out are cleared; rich sections you leave out are kept, and null clears one. |
templateId | string | Optional | Link the card to a different template’s field rules, or null to unlink it. |
Example request
curl -X PATCH "https://api.qrbold.com/api/public/v1/cards/cmf3k2a9x0001" \
-H "Authorization: Bearer $QRBOLD_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"fields": {
"firstName": "Ada",
"lastName": "Lovelace",
"title": "Chief Technology Officer",
"company": "Analytical Engines Ltd",
"photoUrl": "https://example.com/photos/ada.jpg",
"companyLogoUrl": "https://example.com/brand/logo.png",
"bio": "Builds calculating machines and the teams around them.",
"emails": [
{
"label": "Work",
"value": "ada@example.com"
}
],
"phones": [
{
"label": "Mobile",
"value": "+44 20 7946 0958"
}
],
"links": [
{
"type": "website",
"url": "example.com"
},
{
"type": "linkedin",
"url": "linkedin.com/in/ada-lovelace"
}
],
"address": {
"city": "London",
"country": "United Kingdom"
}
}
}'Response
200 The updated card object.
{
"object": "card",
"id": "cmf3k2a9x0001",
"name": "Ada Lovelace",
"shortCode": "ada-lovelace",
"status": "published",
"url": "https://qrbold.com/c/ada-lovelace",
"vcardUrl": "https://qrbold.com/c/ada-lovelace/vcard",
"templateId": "cmf3k1p7d0002",
"externalId": null,
"paused": false,
"fields": {
"firstName": "Ada",
"lastName": "Lovelace",
"title": "Chief Technology Officer",
"company": "Analytical Engines Ltd",
"photoUrl": "https://example.com/photos/ada.jpg",
"companyLogoUrl": "https://example.com/brand/logo.png",
"bio": "Builds calculating machines and the teams around them.",
"emails": [
{
"label": "Work",
"value": "ada@example.com"
}
],
"phones": [
{
"label": "Mobile",
"value": "+44 20 7946 0958"
}
],
"links": [
{
"type": "website",
"url": "example.com"
},
{
"type": "linkedin",
"url": "linkedin.com/in/ada-lovelace"
}
],
"address": {
"city": "London",
"country": "United Kingdom"
}
},
"createdAt": "2026-10-09T09:30:00.000Z",
"updatedAt": "2026-10-09T10:05: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 |
422 | validation_failed | The card’s template does not allow what was sent. | 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
- The public URL and the QR code do not change when a card is updated, so nothing has to be reprinted.
Related
Delete a card
Moves the card to the account’s Trash. Its public URL stops opening immediately.
API key required. Scope: cards: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 card’s id, as returned in the card object. |
Example request
curl -X DELETE "https://api.qrbold.com/api/public/v1/cards/cmf3k2a9x0001" \
-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
- The card can be restored from Trash in the dashboard for the retention period. There is no restore endpoint in the REST API.
- Any printed QR code that points at the card leads to an “unavailable” page until it is restored.
Related
Get wallet links
Returns the links that add the card to Apple Wallet and Google Wallet, and how many passes are installed.
API key required. Scope: cards: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 card’s id, as returned in the card object. |
Example request
curl "https://api.qrbold.com/api/public/v1/cards/cmf3k2a9x0001/wallet" \
-H "Authorization: Bearer $QRBOLD_API_KEY"Response
200 A wallet_links object. A link is null when that wallet cannot issue a pass for this card.
{
"object": "wallet_links",
"cardId": "cmf3k2a9x0001",
"enabled": true,
"apple": "https://qrbold.com/c/ada-lovelace/wallet/apple",
"google": "https://qrbold.com/c/ada-lovelace/wallet/google",
"installs": {
"apple": {
"issued": 12,
"installed": 9
},
"google": {
"issued": 4,
"installed": 3
}
}
}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
- Read-only. The pass design is edited on the card’s Wallet tab in the dashboard.