Getting started
Authentication and API keys
The REST API authenticates with an API key and nothing else. This page covers creating a key, sending it, limiting what it can do, and replacing it safely.
| Question | Answer |
|---|---|
| What authenticates a request? | An API key. Not a dashboard session, not OAuth. |
| Which header? | Authorization: Bearer YOUR_API_KEY, or X-API-Key: YOUR_API_KEY. |
| What does a key look like? | qrb_live_ followed by 43 characters. |
| Where do I get one? | Dashboard → Settings → Developer API |
| Can I see a key again later? | No. It is shown once, when you create it. |
| Can a key be limited? | Yes: by scope, by expiry, and to a single campaign. |
Create an API key
- Open Settings → Developer API in the dashboard.
- Click New API key and name it after the system that will use it.
- Select the scopes it needs, and an expiry if you want one.
- Copy the key from the confirmation screen and store it in your secrets manager.
QRBold keeps only a SHA-256 hash of the key, so the full value exists only on that confirmation screen. If it is lost, create another and revoke the old one. The dashboard afterwards shows just the first characters and the last four, enough to tell keys apart.
How many keys an account may hold at once depends on its plan; see plans and access. Creating keys is limited to people who may manage API keys on the account.
Send the key
Add one header to every request:
Authorization: Bearer YOUR_API_KEYSome tools (Zapier, Make, n8n and similar) only let you set a header name and a value. For those, this is equivalent:
X-API-Key: YOUR_API_KEYIf a request carries both headers, X-API-Key is the one that is read. A key in the query string or in the request body is ignored.
Keep the key out of your source code. The samples read it from the QRBOLD_API_KEY environment variable:
curl "https://api.qrbold.com/api/public/v1/me" \
-H "Authorization: Bearer $QRBOLD_API_KEY"Scopes
A scope is one permission. A key holds only the scopes you ticked when you created it, and an endpoint refuses a key that lacks its scope with 403 forbidden.
| Scope | Lets the key |
|---|---|
cards:read | List and retrieve digital business cards, their wallet links and campaigns. |
cards:write | Create, update and delete digital business cards, including through a campaign. |
templates:read | List and retrieve card templates. |
qr:read | List and retrieve QR codes and their images. |
qr:write | Create, update and delete QR codes. |
analytics:read | Read scan statistics. |
cards:share | Share cards with other people. Used by the AI assistant tools only; no REST endpoint needs it. |
cards:send | Email a card to somebody. Used by the AI assistant tools only; no REST endpoint needs it. |
- Read is not implied by write. A key with only
cards:writecan create a card but cannot list cards. Tick both if you need both. - Scopes are fixed at creation. To change them, create a new key.
- The QR image is the one shared permission. Either
qr:readorcards:readcan download an image, so a cards-only key can fetch the QR code for a card it just created. GET /meneeds no scope.- In the key dialog, the AI assistant preset selects every scope and the Read only preset selects only the read scopes.
Each endpoint’s required scope is listed in the API reference.
Plans and access
QRBold has two plan lines, one for QR codes and one for digital business cards. The REST API is included in the top plan of each. Either one is enough.
| Plan | Line | REST API | Active keys | Requests per minute, per key |
|---|---|---|---|---|
| Free | QR plans | Not included | 1 | 30 |
| Launch | QR plans | Not included | 2 | 60 |
| Growth | QR plans | Not included | 3 | 60 |
| Pro | QR plans | Included | 10 | 120 |
| Free Card | Card plans | Not included | 1 | 30 |
| Team | Card plans | Not included | 3 | 60 |
| Business | Card plans | Included | 10 | 120 |
- Every plan can create keys, because the same keys also connect AI assistants, which every plan includes. On a plan without REST access those keys work with assistants and answer
403 upgrade_required_apion REST. - The plan is checked on every request, not just when the key is made. If an account downgrades, its keys stop working on REST at once and start again if it upgrades.
- When an account holds both lines, it gets the more generous of the two limits.
Campaign-scoped keys
A key can be restricted to one campaign. Such a key can create cards through that campaign’s endpoints and read that campaign, and nothing else: every account-wide endpoint answers 403 key_scoped_to_campaign.
It is the right key to hand to an outside vendor, such as an HR system integrator. They can create the cards they were hired to create and cannot list your account. You create one from the campaign’s API tab in the dashboard (Bulk → the group → API).
Rotate and revoke
Revoke
Click Revoke next to a key on the Developer API page. It stops working on the next request; there is no delay and no undo. A revoked key stays in the list as a record until you delete it.
Rotate without downtime
There is no “regenerate” button, on purpose. Rotation is create, switch, then revoke:
- Create a new key with the same scopes.
- Deploy it to your application.
- Watch Last used on the old key in the dashboard. It updates about once a minute.
- When the old key has gone quiet, revoke it.
Revoking first means your integration is down until the new key is deployed.
Expiry
A key created with an expiry stops working at that time and answers 401 invalid_api_key, the same as a revoked one. Put a reminder in your calendar a week before, and rotate.
If a key leaks
Revoke it immediately, then create a replacement. Because every key starts with qrb_live_, secret scanners in GitHub and similar tools can be given that one pattern to watch for.
What an authentication failure looks like
A missing, mistyped, revoked or expired key all answer the same way:
{
"error": {
"type": "authentication_error",
"code": "invalid_api_key",
"message": "Invalid API key"
}
}The response is deliberately identical for all four, so it does not confirm to a stranger which guesses were once real keys. When the header is absent altogether, the message names both accepted header forms.
A valid key without the needed scope answers 403 instead, and the message names the scope:
{
"error": {
"type": "permission_error",
"code": "forbidden",
"message": "This API key is missing the \"cards:write\" scope. Create a new key with that scope to call this endpoint."
}
}Two things that surprise people: a request with no key at all answers 401 even for a path that does not exist, so an anonymous caller cannot map the API; and a signed-in dashboard session does not authenticate REST requests, only a key does.
Next: core concepts and URLs.