Skip to content
API key

Guide

Create your first digital business card

The whole workflow, not just the endpoint: what a card is, which fields it takes, the request that creates one, and how to check the result a real person will see.

What a digital business card is

A digital business card is a public web page for one person. It shows who they are and how to reach them, and it has a button that saves them to the visitor’s phone contacts. It lives at its own address, such as https://qrbold.com/c/ada-lovelace, and comes with a QR code that opens that address.

A card is made of two parts, and the API treats them differently:

  • Data: the person’s name, title, company, photo, emails, phones, links, address and optional richer sections such as a gallery or testimonials. The API sets and changes this.
  • Design: the layout, colours and which blocks appear. The API does not edit this. A card copies its design from a template when it is created, and after that the design is changed in the dashboard.
What is it?
A public profile page for one person, with a save-to-contacts button and its own QR code.
Why would I use it?
To give employees, sales reps or customers a card without anyone filling in a form by hand.
What do I need first?
An API key with cards:write. Optionally, a template designed in the dashboard.
Which endpoint do I use?
POST /cards with the person’s data.
What result should I expect?
A card object with a permanent id and a public url that opens immediately.

The workflow

  1. Pick a template

    Optional. GET /templates

  2. Prepare the data

    The fields object

  3. Create

    POST /cards

  4. Save the id

    From the response

  5. Open the url

    What people will see

  1. Authenticate
    Send your key in the Authorization header.
  2. Prepare the card data
    Build the fields object.
  3. Check the response
    201, and paused is false.
  4. Save the card id
    You need it for every later call.
  5. Retrieve the card
    Confirm it reads back as you expect.
  6. Find the public URL
    It is the url field. Nothing to construct.
  7. Get the QR code
    Download the image with the card id.
  8. Open the card and check it
    On a phone, signed out.

Choose a template

A template is optional. Leave templateId out and the card gets QRBold’s default starter design, with no rules about which fields you may set. That is the fastest way to a first card.

Use a template when every card should share your company’s design. Templates are built in the dashboard under Digital business cards → Templates; the API cannot create them. To find the id of one:

curl "https://api.qrbold.com/api/public/v1/templates" \
  -H "Authorization: Bearer $QRBOLD_API_KEY"
200 response
{
  "object": "list",
  "data": [
    {
      "object": "card_template",
      "id": "cmf3k1p7d0002",
      "name": "Company standard",
      "policy": {
        "theme": "locked",
        "blocks": "reorder_only",
        "fields": {
          "company": {
            "mode": "locked",
            "value": "Analytical Engines Ltd"
          },
          "firstName": {
            "mode": "required"
          }
        }
      },
      "createdAt": "2026-09-01T08:00:00.000Z",
      "updatedAt": "2026-09-20T14:12:00.000Z"
    }
  ],
  "pagination": {
    "total": 1,
    "limit": 25,
    "offset": 0,
    "hasMore": false
  }
}

The id is what you pass as templateId. Any template in your account works with any card; there is no compatibility to check.

What a template’s policy means

policy.fields lists rules for individual fields. Fields that are not listed are free to set.

Template field modes
ModeWhat it means for your request
lockedThe template supplies the value. Do not send this field; sending a different value answers 422.
hiddenThe card does not have this field. Do not send it.
requiredYou must send a non-empty value.
prefilledThe template supplies a default that you may override.
optionalSend it or not.

In the example above, company is locked and firstName is required. The server enforces these rules for API requests exactly as it does in the dashboard.

Card fields

All of a person’s data goes in one object called fields. Every field is optional as far as the API is concerned; a field becomes required only when the card’s template says so. In practice, send at least firstName and lastName: they become the card’s name.

Identity

Identity fields
NameTypeRequiredDescription
prefixstringOptionalUp to 20 characters, e.g. "Dr".
firstNamestringOptionalUp to 200 characters.
middleNamestringOptionalUp to 200 characters.
lastNamestringOptionalUp to 200 characters.
suffixstringOptionalUp to 20 characters, e.g. "PhD".
preferredNamestringOptionalThe name the person goes by.
pronounsstringOptionalUp to 40 characters.
accreditationsarrayOptionalUp to 10 strings of 50 characters, e.g. ["CPA", "MBA"].

Role

Role fields
NameTypeRequiredDescription
titlestringOptionalJob title.
departmentstringOptionalDepartment or team.
companystringOptionalCompany name.

Media

Media fields
NameTypeRequiredDescription
photoUrlstringOptionalA publicly reachable URL of the profile photo. The API takes a link, not a file upload.
coverUrlstringOptionalURL of the cover image.
companyLogoUrlstringOptionalURL of the company logo.
biostringOptionalUp to 2,000 characters.

Contact

Contact fields
NameTypeRequiredDescription
emailsarrayOptionalUp to 10 items of { label, value }.
phonesarrayOptionalUp to 10 items of { label, value }.
linksarrayOptionalUp to 20 items of { type, url, label?, subtitle?, iconUrl?, enabled? }. type is one of website, linkedin, x, instagram, facebook, youtube, github, whatsapp, calendly, tiktok, telegram, custom.
addressobjectOptional{ line1, line2, city, state, postalCode, country }, all optional.

Rich sections

Rich sections fields
NameTypeRequiredDescription
aboutobjectOptional{ heading, body, imageUrl, signatureUrl, highlights[], milestones[], stats[] }.
galleryarrayOptionalUp to 24 items of { url, caption?, ratio? }.
videosarrayOptionalUp to 12 items of { url, title?, description?, thumbnailUrl?, duration? }.
teamarrayOptionalUp to 24 items of { name, title?, photoUrl?, links? }.
testimonialsarrayOptionalUp to 24 items of { quote, author, authorTitle?, authorPhotoUrl?, rating? } (rating 1 to 5).
productsarrayOptionalUp to 24 items of { name, description?, imageUrl?, price?, category?, ctaLabel?, ctaUrl? }.

Custom

Custom fields
NameTypeRequiredDescription
customobjectOptionalA flat map of string keys to string values, for fields your template declares.
  • Text limits: short text fields take up to 200 characters, and bio and descriptions up to 2,000.
  • URLs can be bare domains. example.com is accepted as well as https://example.com. mailto: and tel: links are accepted too.
  • Images are links. photoUrl, coverUrl and companyLogoUrl must point at an image that is already public on the internet. The API has no upload.
  • Link types: website, linkedin, x, instagram, facebook, youtube, github, whatsapp, calendly, tiktok, telegram, custom. Use custom with a label for anything else.
  • Defaults: a field you leave out is simply absent from the card. Nothing is filled in for you unless the template pre-fills or locks it.
  • Plans: no field is restricted to a particular plan. Plans limit how many cards an account may have, not what a card contains.

Create the card

POST/cards

This request creates a complete card for a fictional person. Replace the values with your own, and replace or remove templateId and shortCode.

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"
      }
    }
  }'

The request body, field by field

POST /cards body
NameTypeRequiredDescription
fieldsobjectOptionalThe person’s data. See the card fields table. Defaults to an empty object, but a template may require some fields.
namestringOptionalLabel shown in the dashboard, 1 to 200 characters. Default: first + last name.
templateIdstringOptionalCopies this template’s design onto the card and applies its field rules. Default: the default starter design.
shortCodestringOptionalCustom slug for the public URL: letters, numbers and hyphens, up to 100 characters. Default: a random 8-character code.
statusstringOptionalpublished 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.

Headers

  • Authorization: Bearer YOUR_API_KEY, required.
  • Content-Type: application/json, required.
  • Idempotency-Key, optional but recommended: any unique value, such as a UUID. If the request times out and you send it again with the same key, you get the original response back instead of a second card. See idempotency.

Read the response

Success is 201 Created with the card object:

201 response
{
  "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"
}
Card object fields
FieldWhat it is
idSave this. The permanent identifier you pass to every other card endpoint.
urlThe public card page. This is what you share and what the QR code contains.
vcardUrlA link that downloads the contact as a .vcf file. Point a “Save contact” button at it.
shortCodeThe last part of url. Yours if you sent one, otherwise random.
nameThe label in the dashboard. Follows the person’s name.
statuspublished unless you asked for draft.
pausedtrue means the account’s plan does not currently cover this card and its page will not open.
templateIdThe template it was created from, or null.
externalIdYour own identifier. Only set for cards created through a campaign; null otherwise.
fieldsThe data as stored, after the template’s rules were applied.
createdAt, updatedAtISO 8601 timestamps in UTC.

A card is live when status is published and paused is false. Check both before you print anything.

Common errors

Common errors when creating a card
Status and codeWhyWhat to do
422 validation_failedA value has the wrong type, is too long, or is not in an allowed set, such as an unknown link type.Fix the fields named in error.details.
422 validation_failedThe template locks or hides a field you sent, or requires one you left out.Each entry in details has a key and a reason of locked, hidden or required.
403 limit_exhausted_cardsThe account already has as many cards as its plan covers. Nothing was created.Add cards to the plan, or delete unused ones.
400 invalid_requestThe shortCode you asked for is taken.Choose another, or omit it.
400 reserved_short_linkThe shortCode is a reserved word such as login.Choose another.
404 resource_not_foundThe templateId does not exist in this account.List templates and use a real id.

A template violation looks like this. Every problem is listed at once:

422 response
{
  "error": {
    "type": "invalid_request",
    "code": "validation_failed",
    "message": "Some fields could not be saved.",
    "details": [
      {
        "key": "company",
        "reason": "locked"
      },
      {
        "key": "firstName",
        "reason": "required"
      }
    ]
  }
}

What happens after creation

What is true about a card once it is created
QuestionAnswer
Is it published immediately?Yes, unless you sent status: "draft". There is no separate publish step.
Is any activation needed?No. The public URL works as soon as the response arrives.
How do I get the public URL?Read url. Do not build it yourself: accounts with a custom domain get that domain in url.
Does it have a unique identifier?Two: the id (for the API) and the shortCode (in the URL). Both are unique.
Can I choose the slug?Yes, with shortCode at creation. See short links.
What if the slug is taken?The request fails with 400 and nothing is created. A slug is never silently changed or suffixed.
Does it already have a QR code?Yes. Every card has one. You only need to download the image.
Does it count toward my plan?Yes. One card uses one card seat until it is deleted.

Creating a card, publishing it and creating its QR code are therefore one operation in QRBold, not three. The only separate step is downloading the QR image.

Retrieve a card

By id:

GET/cards/:id
curl "https://api.qrbold.com/api/public/v1/cards/cmf3k2a9x0001" \
  -H "Authorization: Bearer $QRBOLD_API_KEY"

It returns the same card object as creation. If you did not store the id, find the card by name with the list endpoint. search matches part of the name:

curl "https://api.qrbold.com/api/public/v1/cards?search=Lovelace" \
  -H "Authorization: Bearer $QRBOLD_API_KEY"

Lists are paged, 25 at a time by default. See pagination.

Update a card

PATCH/cards/:id

So the safe way to change one thing is read, modify, write:

  1. GET /cards/:id and take its fields.
  2. Change what you need in that object.
  3. PATCH /cards/:id with the whole object.

This example changes Ada’s title and keeps everything else:

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"
      }
    }
  }'
  • The card’s id, url and QR code do not change. Nothing needs reprinting.
  • The card’s name follows the person’s name automatically.
  • Only fields and templateId can be sent. Status, slug and design cannot be changed through the API; an unknown key here answers 422.
  • The template’s rules apply to updates just as they do to creation.

Delete a card

DELETE/cards/:id
curl -X DELETE "https://api.qrbold.com/api/public/v1/cards/cmf3k2a9x0001" \
  -H "Authorization: Bearer $QRBOLD_API_KEY"

It answers 204 with no body. The card moves to the account’s Trash, and three things follow:

  • Its public URL stops opening straight away, and visitors see an “unavailable” page.
  • Its QR code stops working too, because the QR code points at that URL. A printed code for a deleted card leads nowhere.
  • It can be restored from Trash in the dashboard for 30 days, which brings the URL and the QR code back. The API cannot restore it.

There is no “deactivate” in the card API. To take a card offline without deleting it, pause or unpublish it in the dashboard.

See the result

Open the url from the response, for example https://qrbold.com/c/ada-lovelace, and check:

  • The page opens in a private browser window, where you are not signed in to QRBold.
  • The name, title, photo and contact details are the ones you sent.
  • The save-contact button downloads a contact. You can test the file directly at vcardUrl.
  • It reads well on a phone, since that is where almost every visitor will see it.
  • The same card appears in the dashboard under Digital business cards.

Next: generate the QR code for this card, using the id you just saved (cmf3k2a9x0001 in these examples).