QR codes

Create QR codes for links, style them, add logos and download images.

A QR code points at one of your links, so you can change where it goes later without reprinting. Scans are counted separately from other clicks.

Every path below starts with https://bgum.me/api/v1/workspaces/{workspaceId}. Send your API key in the Authorization header as described in the API overview.

OperationMethod and path
Create a QR codePOST /qr-codes
List QR codesGET /qr-codes
Get a QR codeGET /qr-codes/{qrId}
Change a QR codePATCH /qr-codes/{qrId}
Archive a QR codeDELETE /qr-codes/{qrId}
Download a QR code imageGET /qr-codes/{qrId}/image.{format}
Add or replace a logoPUT /qr-codes/{qrId}/logo
Remove the logoDELETE /qr-codes/{qrId}/logo

Create a QR code

POST /qr-codes

Creates a QR code for a link. Uses one of the organisation's monthly QR code allowance.

Full path
/api/v1/workspaces/{workspaceId}/qr-codes
API key scope
qr:write
Role needed
Manager or above

Path parameters

NameTypeRequiredDescription
workspaceId string Yes Your workspace ID, from Settings → Workspace.

Request body

JSON (Content-Type: application/json). Leave out fields you don't need.

NameTypeRequiredDescription
linkId string Yes The link the code opens.
name string No A name to recognise it by, up to 200 characters. Defaults to the link's title or back-half.
foreground string No Hex colour of the dark squares, e.g. #15181C (Pro and above).
background string No Hex colour of the background, e.g. #FFFFFF (Pro and above). Must be lighter than the foreground, with contrast of at least 4:1.
errorCorrection string No Low, Medium (default), Quartile or High (Pro and above). Higher survives more damage but makes a denser code.
quietZone integer No Blank margin in modules, 2 to 10. Default 4 (Pro and above).

Example request

curl

curl -X POST "https://bgum.me/api/v1/workspaces/$WORKSPACE_ID/qr-codes" \
  -H "Authorization: Bearer $BGL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "linkId": "ZiZihoWXe3as",
  "name": "Shop window poster"
}'

JavaScript

const res = await fetch(`https://bgum.me/api/v1/workspaces/${process.env.WORKSPACE_ID}/qr-codes`, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.BGL_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "linkId": "ZiZihoWXe3as",
    "name": "Shop window poster"
  }),
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
const data = await res.json();
console.log(data);

Python

import os
import requests

res = requests.post(
    f"https://bgum.me/api/v1/workspaces/{os.environ['WORKSPACE_ID']}/qr-codes",
    headers={
        "Authorization": f"Bearer {os.environ['BGL_API_KEY']}",
    },
    json={
        "linkId": "ZiZihoWXe3as",
        "name": "Shop window poster",
    },
    timeout=30,
)
res.raise_for_status()
print(res.json())

Response

201 Created · application/json

JSON

{
  "id": "pSchXlIk",
  "name": "Shop window poster",
  "linkId": "ZiZihoWXe3as",
  "shortUrl": "https://bgum.me/spring-sale",
  "encodedUrl": "https://bgum.me/spring-sale?qr=pSchXlIk",
  "destinationUrl": "https://example.com/spring-sale",
  "foreground": "#15181C",
  "background": "#FFFFFF",
  "errorCorrection": "Medium",
  "quietZone": 4,
  "version": 3,
  "scans": 0,
  "createdAt": "2026-10-14T22:49:36.4637149+00:00",
  "archived": false,
  "hasLogo": false
}

Good to know

  • encodedUrl is what the code contains: the short link plus ?qr= and the code's ID, which is how scans are told apart from clicks.

Errors

StatusCodeMeaning
404link.not_foundNo link with that ID in this workspace (or it was deleted).
422qr.colour_invalidA colour isn't a six-digit hex value.
422qr.invertedThe foreground is lighter than the background. Many scanners can't read that.
422qr.low_contrastThe colours are too close together to scan reliably (contrast below 4:1).
422qr.quiet_zone_invalidThe margin is outside 2 to 10 modules.
422qr.error_correction_invaliderrorCorrection isn't one of the allowed values.
429quota.qr_exhaustedThe organisation has used this month's allowance of new QR codes. The response has limit and resetsAt fields.
409qr.id_generation_failedWe couldn't generate a unique QR code ID.

Any request can also return the general errors: 401 for a missing or wrong key, 403 for a missing scope or plan feature, 404 for an unknown workspace and 429 when you're sending too fast.

List QR codes

GET /qr-codes

Lists the workspace's QR codes, newest first (up to 500).

Full path
/api/v1/workspaces/{workspaceId}/qr-codes
API key scope
links:read
Role needed
Viewer or above

Path parameters

NameTypeRequiredDescription
workspaceId string Yes Your workspace ID, from Settings → Workspace.

Query parameters

NameTypeRequiredDescription
linkId string No Only QR codes for this link.
includeArchived boolean No true includes archived QR codes. Default false.

Example request

curl

curl "https://bgum.me/api/v1/workspaces/$WORKSPACE_ID/qr-codes?linkId=ZiZihoWXe3as" \
  -H "Authorization: Bearer $BGL_API_KEY"

JavaScript

const res = await fetch(`https://bgum.me/api/v1/workspaces/${process.env.WORKSPACE_ID}/qr-codes?linkId=ZiZihoWXe3as`, {
  headers: {
    Authorization: `Bearer ${process.env.BGL_API_KEY}`,
  },
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
const data = await res.json();
console.log(data);

Python

import os
import requests

res = requests.get(
    f"https://bgum.me/api/v1/workspaces/{os.environ['WORKSPACE_ID']}/qr-codes?linkId=ZiZihoWXe3as",
    headers={
        "Authorization": f"Bearer {os.environ['BGL_API_KEY']}",
    },
    timeout=30,
)
res.raise_for_status()
print(res.json())

Response

200 OK · application/json

JSON

{
  "items": [
    {
      "id": "pSchXlIk",
      "name": "Shop window poster",
      "linkId": "ZiZihoWXe3as",
      "shortUrl": "https://bgum.me/spring-sale",
      "encodedUrl": "https://bgum.me/spring-sale?qr=pSchXlIk",
      "destinationUrl": "https://example.com/spring-sale",
      "foreground": "#15181C",
      "background": "#FFFFFF",
      "errorCorrection": "Medium",
      "quietZone": 4,
      "version": 3,
      "scans": 0,
      "createdAt": "2026-10-14T22:49:36.4637149+00:00",
      "archived": false,
      "hasLogo": false
    }
  ]
}

Errors

Any request can also return the general errors: 401 for a missing or wrong key, 403 for a missing scope or plan feature, 404 for an unknown workspace and 429 when you're sending too fast.

Get a QR code

GET /qr-codes/{qrId}

Returns one QR code with its scan count.

Full path
/api/v1/workspaces/{workspaceId}/qr-codes/{qrId}
API key scope
links:read
Role needed
Viewer or above

Path parameters

NameTypeRequiredDescription
workspaceId string Yes Your workspace ID, from Settings → Workspace.
qrId string Yes The QR code's ID, as returned when it was created or listed.

Example request

curl

curl "https://bgum.me/api/v1/workspaces/$WORKSPACE_ID/qr-codes/pSchXlIk" \
  -H "Authorization: Bearer $BGL_API_KEY"

JavaScript

const res = await fetch(`https://bgum.me/api/v1/workspaces/${process.env.WORKSPACE_ID}/qr-codes/pSchXlIk`, {
  headers: {
    Authorization: `Bearer ${process.env.BGL_API_KEY}`,
  },
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
const data = await res.json();
console.log(data);

Python

import os
import requests

res = requests.get(
    f"https://bgum.me/api/v1/workspaces/{os.environ['WORKSPACE_ID']}/qr-codes/pSchXlIk",
    headers={
        "Authorization": f"Bearer {os.environ['BGL_API_KEY']}",
    },
    timeout=30,
)
res.raise_for_status()
print(res.json())

Response

200 OK · application/json

JSON

{
  "id": "pSchXlIk",
  "name": "Shop window poster",
  "linkId": "ZiZihoWXe3as",
  "shortUrl": "https://bgum.me/spring-sale",
  "encodedUrl": "https://bgum.me/spring-sale?qr=pSchXlIk",
  "destinationUrl": "https://example.com/spring-sale",
  "foreground": "#15181C",
  "background": "#FFFFFF",
  "errorCorrection": "Medium",
  "quietZone": 4,
  "version": 3,
  "scans": 0,
  "createdAt": "2026-10-14T22:49:36.4637149+00:00",
  "archived": false,
  "hasLogo": false
}

Errors

StatusCodeMeaning
404qr.not_foundNo QR code with that ID in this workspace.

Any request can also return the general errors: 401 for a missing or wrong key, 403 for a missing scope or plan feature, 404 for an unknown workspace and 429 when you're sending too fast.

Change a QR code

PATCH /qr-codes/{qrId}

Renames or restyles a QR code. Only the fields you send change. Printed copies keep working, but reprint them to match a new style.

Full path
/api/v1/workspaces/{workspaceId}/qr-codes/{qrId}
API key scope
qr:write
Role needed
Manager or above

Path parameters

NameTypeRequiredDescription
workspaceId string Yes Your workspace ID, from Settings → Workspace.
qrId string Yes The QR code's ID, as returned when it was created or listed.

Request body

JSON (Content-Type: application/json). Leave out fields you don't need.

NameTypeRequiredDescription
name string No New name.
foreground string No Hex colour of the dark squares.
background string No Hex colour of the background.
errorCorrection string No Low, Medium, Quartile or High. Codes with a logo must stay High.
quietZone integer No Margin in modules, 2 to 10.

Example request

curl

curl -X PATCH "https://bgum.me/api/v1/workspaces/$WORKSPACE_ID/qr-codes/pSchXlIk" \
  -H "Authorization: Bearer $BGL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "foreground": "#0B3D2E",
  "background": "#FFFFFF"
}'

JavaScript

const res = await fetch(`https://bgum.me/api/v1/workspaces/${process.env.WORKSPACE_ID}/qr-codes/pSchXlIk`, {
  method: "PATCH",
  headers: {
    Authorization: `Bearer ${process.env.BGL_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "foreground": "#0B3D2E",
    "background": "#FFFFFF"
  }),
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
const data = await res.json();
console.log(data);

Python

import os
import requests

res = requests.patch(
    f"https://bgum.me/api/v1/workspaces/{os.environ['WORKSPACE_ID']}/qr-codes/pSchXlIk",
    headers={
        "Authorization": f"Bearer {os.environ['BGL_API_KEY']}",
    },
    json={
        "foreground": "#0B3D2E",
        "background": "#FFFFFF",
    },
    timeout=30,
)
res.raise_for_status()
print(res.json())

Response

200 OK · application/json

JSON

{
  "id": "pSchXlIk",
  "name": "Shop window poster",
  "linkId": "ZiZihoWXe3as",
  "shortUrl": "https://bgum.me/spring-sale",
  "encodedUrl": "https://bgum.me/spring-sale?qr=pSchXlIk",
  "destinationUrl": "https://example.com/spring-sale",
  "foreground": "#0B3D2E",
  "background": "#FFFFFF",
  "errorCorrection": "Medium",
  "quietZone": 4,
  "version": 3,
  "scans": 0,
  "createdAt": "2026-10-14T22:49:36.4637149+00:00",
  "archived": false,
  "hasLogo": false
}

Errors

StatusCodeMeaning
404qr.not_foundNo QR code with that ID in this workspace.
422qr.colour_invalidA colour isn't a six-digit hex value.
422qr.invertedThe foreground is lighter than the background. Many scanners can't read that.
422qr.low_contrastThe colours are too close together to scan reliably (contrast below 4:1).
422qr.quiet_zone_invalidThe margin is outside 2 to 10 modules.
422qr.error_correction_invaliderrorCorrection isn't one of the allowed values.
422qr.logo_needs_highCodes with a logo must use High error correction.

Any request can also return the general errors: 401 for a missing or wrong key, 403 for a missing scope or plan feature, 404 for an unknown workspace and 429 when you're sending too fast.

Archive a QR code

DELETE /qr-codes/{qrId}

Hides the QR code from lists. Printed copies keep working, because the link does.

Full path
/api/v1/workspaces/{workspaceId}/qr-codes/{qrId}
API key scope
qr:write
Role needed
Manager or above

Path parameters

NameTypeRequiredDescription
workspaceId string Yes Your workspace ID, from Settings → Workspace.
qrId string Yes The QR code's ID, as returned when it was created or listed.

Example request

curl

curl -X DELETE "https://bgum.me/api/v1/workspaces/$WORKSPACE_ID/qr-codes/pSchXlIk" \
  -H "Authorization: Bearer $BGL_API_KEY"

JavaScript

const res = await fetch(`https://bgum.me/api/v1/workspaces/${process.env.WORKSPACE_ID}/qr-codes/pSchXlIk`, {
  method: "DELETE",
  headers: {
    Authorization: `Bearer ${process.env.BGL_API_KEY}`,
  },
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
// 204 No Content: nothing to read.

Python

import os
import requests

res = requests.delete(
    f"https://bgum.me/api/v1/workspaces/{os.environ['WORKSPACE_ID']}/qr-codes/pSchXlIk",
    headers={
        "Authorization": f"Bearer {os.environ['BGL_API_KEY']}",
    },
    timeout=30,
)
res.raise_for_status()
# 204 No Content: nothing to read.

Response

204 No Content

Good to know

  • To stop printed codes working, pause or delete the link instead.

Errors

StatusCodeMeaning
404qr.not_foundNo QR code with that ID in this workspace.

Any request can also return the general errors: 401 for a missing or wrong key, 403 for a missing scope or plan feature, 404 for an unknown workspace and 429 when you're sending too fast.

Download a QR code image

GET /qr-codes/{qrId}/image.{format}

Returns the QR code as a PNG, SVG or vector PDF.

Full path
/api/v1/workspaces/{workspaceId}/qr-codes/{qrId}/image.{format}
API key scope
links:read
Role needed
Viewer or above

Path parameters

NameTypeRequiredDescription
workspaceId string Yes Your workspace ID, from Settings → Workspace.
qrId string Yes The QR code's ID, as returned when it was created or listed.
format string Yes png (300 dpi), svg (scales to any size) or pdf (vector, 50 mm square including the margin).

Query parameters

NameTypeRequiredDescription
size integer No PNG only: width in pixels, 128 to 4,096. Default 1,024. Squares are whole pixels, so the image can be slightly smaller.

Example request

curl

curl "https://bgum.me/api/v1/workspaces/$WORKSPACE_ID/qr-codes/pSchXlIk/image.png?size=2048" \
  -H "Authorization: Bearer $BGL_API_KEY" \
  -o qr.png

JavaScript

const res = await fetch(`https://bgum.me/api/v1/workspaces/${process.env.WORKSPACE_ID}/qr-codes/pSchXlIk/image.png?size=2048`, {
  headers: {
    Authorization: `Bearer ${process.env.BGL_API_KEY}`,
  },
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
const file = Buffer.from(await res.arrayBuffer()); // save as qr.png

Python

import os
import requests

res = requests.get(
    f"https://bgum.me/api/v1/workspaces/{os.environ['WORKSPACE_ID']}/qr-codes/pSchXlIk/image.png?size=2048",
    headers={
        "Authorization": f"Bearer {os.environ['BGL_API_KEY']}",
    },
    timeout=30,
)
res.raise_for_status()
open("qr.png", "wb").write(res.content)

Response

200 OK · image/png, image/svg+xml or application/pdf

Good to know

  • An unknown format returns 404.

Errors

StatusCodeMeaning
404qr.not_foundNo QR code with that ID in this workspace.

Any request can also return the general errors: 401 for a missing or wrong key, 403 for a missing scope or plan feature, 404 for an unknown workspace and 429 when you're sending too fast.

PUT /qr-codes/{qrId}/logo

Puts a PNG logo in the middle of the code (Business). The code switches to High error correction so it still scans.

Full path
/api/v1/workspaces/{workspaceId}/qr-codes/{qrId}/logo
API key scope
qr:write
Role needed
Manager or above
Plan
Needs qr code logos in your plan (compare plans)

Path parameters

NameTypeRequiredDescription
workspaceId string Yes Your workspace ID, from Settings → Workspace.
qrId string Yes The QR code's ID, as returned when it was created or listed.

Request body

The file itself, sent as Content-Type: image/png.

Example request

curl

curl -X PUT "https://bgum.me/api/v1/workspaces/$WORKSPACE_ID/qr-codes/pSchXlIk/logo" \
  -H "Authorization: Bearer $BGL_API_KEY" \
  -H "Content-Type: image/png" \
  --data-binary @logo.png

JavaScript

import { readFile } from "node:fs/promises";

const res = await fetch(`https://bgum.me/api/v1/workspaces/${process.env.WORKSPACE_ID}/qr-codes/pSchXlIk/logo`, {
  method: "PUT",
  headers: {
    Authorization: `Bearer ${process.env.BGL_API_KEY}`,
    "Content-Type": "image/png",
  },
  body: await readFile("logo.png"),
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
const data = await res.json();
console.log(data);

Python

import os
import requests

res = requests.put(
    f"https://bgum.me/api/v1/workspaces/{os.environ['WORKSPACE_ID']}/qr-codes/pSchXlIk/logo",
    headers={
        "Authorization": f"Bearer {os.environ['BGL_API_KEY']}",
        "Content-Type": "image/png",
    },
    data=open("logo.png", "rb").read(),
    timeout=30,
)
res.raise_for_status()
print(res.json())

Response

200 OK · application/json

JSON

{
  "id": "pSchXlIk",
  "name": "Shop window poster",
  "linkId": "ZiZihoWXe3as",
  "shortUrl": "https://bgum.me/spring-sale",
  "encodedUrl": "https://bgum.me/spring-sale?qr=pSchXlIk",
  "destinationUrl": "https://example.com/spring-sale",
  "foreground": "#15181C",
  "background": "#FFFFFF",
  "errorCorrection": "High",
  "quietZone": 4,
  "version": 3,
  "scans": 0,
  "createdAt": "2026-10-14T22:49:36.4637149+00:00",
  "archived": false,
  "hasLogo": true
}

Good to know

  • Send the PNG file itself as the request body, not as a form. Up to 256 KB; larger requests get 413.
  • A square logo with a transparent background works best. Test a printed copy before a big print run.

Errors

StatusCodeMeaning
404qr.not_foundNo QR code with that ID in this workspace.
422qr.logo_sizeThe logo is empty or larger than 256 KB.
422qr.logo_invalidThe logo isn't a PNG we can read.
422qr.logo_smallThe logo is smaller than 16 × 16 pixels.

Any request can also return the general errors: 401 for a missing or wrong key, 403 for a missing scope or plan feature, 404 for an unknown workspace and 429 when you're sending too fast.

DELETE /qr-codes/{qrId}/logo

Removes the logo. The code keeps High error correction until you change it.

Full path
/api/v1/workspaces/{workspaceId}/qr-codes/{qrId}/logo
API key scope
qr:write
Role needed
Manager or above

Path parameters

NameTypeRequiredDescription
workspaceId string Yes Your workspace ID, from Settings → Workspace.
qrId string Yes The QR code's ID, as returned when it was created or listed.

Example request

curl

curl -X DELETE "https://bgum.me/api/v1/workspaces/$WORKSPACE_ID/qr-codes/pSchXlIk/logo" \
  -H "Authorization: Bearer $BGL_API_KEY"

JavaScript

const res = await fetch(`https://bgum.me/api/v1/workspaces/${process.env.WORKSPACE_ID}/qr-codes/pSchXlIk/logo`, {
  method: "DELETE",
  headers: {
    Authorization: `Bearer ${process.env.BGL_API_KEY}`,
  },
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
const data = await res.json();
console.log(data);

Python

import os
import requests

res = requests.delete(
    f"https://bgum.me/api/v1/workspaces/{os.environ['WORKSPACE_ID']}/qr-codes/pSchXlIk/logo",
    headers={
        "Authorization": f"Bearer {os.environ['BGL_API_KEY']}",
    },
    timeout=30,
)
res.raise_for_status()
print(res.json())

Response

200 OK · application/json

JSON

{
  "id": "pSchXlIk",
  "name": "Shop window poster",
  "linkId": "ZiZihoWXe3as",
  "shortUrl": "https://bgum.me/spring-sale",
  "encodedUrl": "https://bgum.me/spring-sale?qr=pSchXlIk",
  "destinationUrl": "https://example.com/spring-sale",
  "foreground": "#15181C",
  "background": "#FFFFFF",
  "errorCorrection": "High",
  "quietZone": 4,
  "version": 3,
  "scans": 0,
  "createdAt": "2026-10-14T22:49:36.4637149+00:00",
  "archived": false,
  "hasLogo": false
}

Errors

StatusCodeMeaning
404qr.not_foundNo QR code with that ID in this workspace.

Any request can also return the general errors: 401 for a missing or wrong key, 403 for a missing scope or plan feature, 404 for an unknown workspace and 429 when you're sending too fast.

Something missing or unclear? Tell us and we'll improve this page.