QRdx
HelpGuidesDevelopersReact librarySelf-hosting

Barcode API

Make EAN, UPC, Code 128, Data Matrix and other barcode images from a URL, with no API key, and keep barcodes in a workspace with the REST API.

GET https://api.qrdx.dev/v1/barcode returns a barcode image. Everything is in the query string, so the URL is the image: put it in an <img> tag, a product feed or a label template. It draws the same 11 formats as the barcode generator, with the same rules, and gives back the same SVG.

<img
  src="https://api.qrdx.dev/v1/barcode?format=ean13&data=590123412345"
  alt="EAN-13 barcode 5901234123457"
/>

That number is one digit short, so the check digit (7) is added. Send all 13 digits and the check digit is verified instead: a wrong one returns 400 and says what it should be.

No account or API key is needed. To keep barcodes in your workspace and edit them later, use saved barcodes.

Examples

A PNG at 3 pixels per module (quote the URL so your shell keeps the &):

curl -o box.png "https://api.qrdx.dev/v1/barcode?format=ean13&data=5901234123457&type=png&scale=3"

A vector PDF of a GS1-128 logistics label, with brackets around each Application Identifier:

curl -o pallet.pdf "https://api.qrdx.dev/v1/barcode?format=gs1-128&type=pdf&data=(01)09501101530003(17)261231(10)AB-123"

Encode values that contain &, #, + or spaces, for example with encodeURIComponent in JavaScript.

A Code 128 shelf label in dark blue, without the text under the bars, turned 90°:

https://api.qrdx.dev/v1/barcode?format=code128&data=SHELF-A12&fg=1e3a8a&text=false&rotate=90

A Data Matrix with a wider margin:

https://api.qrdx.dev/v1/barcode?format=datamatrix&data=SN-0042-7781&quietZone=4

Parameters

ParameterDefaultDescription
formatrequiredThe barcode type; see Formats. Case and dashes don't matter: EAN-13 works too
datarequiredThe number or text to encode, up to 1,000 characters (less for most linear formats)
typesvgsvg, png, jpg, webp, avif, pdf or eps
scale4Pixels per module in PNG, JPG, WebP and AVIF, 1 to 10
heightdepends on the formatBar height of linear barcodes in millimetres at the vector size, 5 to 60 (23 for EAN-13)
quietZonethe format's minimumBlank margin in modules: each side of linear barcodes (0 to 20), all round 2D codes (0 to 10)
texttruePrint the digits or text under linear barcodes
fg000000Bars and text, as hex
bgffffffBackground, as hex
rotate0Clockwise rotation: 0, 90, 180 or 270

Write colors without the #, or encode it as %23.

Formats

formatBarcodeTakes
ean13EAN-1312 digits (check digit added) or 13 (checked)
ean8EAN-87 digits or 8
upcaUPC-A11 digits or 12
upceUPC-E6 to 8 digits, or a 12-digit UPC-A that can be shortened
itf14ITF-1413 digits or 14
gs1-128GS1-128Application Identifiers in brackets with their values; GTIN and SSCC check digits added or checked; up to 48 characters of data
code128Code 128Up to 80 printable ASCII characters
code39Code 39Up to 40 capitals, digits, spaces and - . $ / + %
datamatrixData MatrixAny text up to 1,000 characters
pdf417PDF417Any text up to 1,000 characters
aztecAztecAny text up to 1,000 characters

Retail numbers (EAN, UPC, ITF-14, GS1-128's GTIN) are licensed to companies by GS1. The API draws any valid number; it doesn't issue or register them.

Sizes

PNG, JPG, WebP and AVIF are scale pixels per module, the narrowest bar's width. A 2D cell is two modules wide.

SVG, PDF and EPS are vectors at one point per module (0.353 mm), so an EAN-13 at the defaults is printed at about 107% of its nominal size. Scale vector files in your layout; for retail barcodes, keep between 80% and 200% and don't cut the bar height.

Responses

A successful request returns the file with:

  • Content-Type of the file type. EPS comes as a download (Content-Disposition: attachment); the rest open inline with a file name such as ean13-5901234123457.png
  • Cache-Control: public, max-age=31536000, immutable: the same query always returns the same bytes
  • Access-Control-Allow-Origin: *, so you can fetch it from any website

A missing or invalid parameter, or a value the format can't hold, returns 400 and names the problem:

{
  "code": "VALIDATION_ERROR",
  "message": "Invalid query parameters",
  "data": {
    "details": [
      {
        "param": "data",
        "message": "EAN-13: The check digit should be 7, not 8. Check the number, or leave the last digit off and it's worked out for you."
      }
    ]
  },
  "status": 400
}

Keep the value out of the URL

POST https://api.qrdx.dev/v1/barcode takes the same fields as JSON and returns the same file, uncached. Use it when the value shouldn't end up in logs, history or caches the way a URL can:

curl -o label.png https://api.qrdx.dev/v1/barcode \
  -H "Content-Type: application/json" \
  -d '{"format":"datamatrix","data":"Internal note 42","type":"png"}'

In JSON, text is a boolean and scale, height, quietZone and rotate are numbers.

Saved barcodes

With an API key, the REST API keeps barcodes in the key's workspace, where they show under Barcodes in the dashboard. Same scopes as codes: codes:read to list and download, codes:write to change.

curl https://api.qrdx.dev/v1/barcodes \
  -H "Authorization: Bearer $QRDX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"format":"ean13","value":"590123412345","title":"Spring box"}'
EndpointDoes
GET /v1/barcodesLists them, newest change first; filter with q, format, folderId, status=trash
POST /v1/barcodesSaves one. options takes foreground, background, showText, barHeightMm, quietZone, scale and rotation
GET /v1/barcodes/{id}One barcode
PATCH /v1/barcodes/{id}Changes its title, format, value, options or folder
DELETE /v1/barcodes/{id}Moves it to the trash; ?permanent=true deletes it for good
GET /v1/barcodes/{id}/imageThe file, drawn as saved: type and scale as above

Each saved barcode has an imageUrl: the same picture from GET /v1/barcode, which anyone with the link can load. The /image endpoint is private and needs the key.

Every plan saves barcodes: up to 1,000 on Free, 10,000 on Pro and 100,000 on Business, not counting the trash. These requests count toward the workspace's daily API quota and send the X-RateLimit-* headers, like the REST API.

MCP

The MCP server has generate_barcode, which checks the value and returns a PNG with image URLs, and save_barcode, which saves to the workspace of the API key on the connection.

Limits

  • Rate limit: 300 requests per minute per IP address for GET and POST /v1/barcode, as for the QR image API. Over the limit you get 429 with a Retry-After header. Saved barcodes follow the REST API's per-minute limits and daily quota.
  • Image size: raster images are at most 6,000 pixels on a side. Lower scale for long values.
  • No scan check here. The barcode generator decodes what it draws before you download; the API draws what you ask for. Print a test and scan it with the scanners that will read it.

Self-hosting

The endpoints are part of the QRdx web app, so a self-hosted instance serves them at /api/v1/barcode and /api/v1/barcodes on your own domain.

Last updated on

On this page