Developers

API reference

Every route uses the same resolver. A valid GTIN becomes a retail barcode. An http or https URL, including a GS1 Digital Link, becomes a QR code. Anything else needs a symbology name. The image address is public.

Base URL
https://beepable.app
For agents
llms.txt

Quickstart

  1. Create a key

    Sign in, open Account, and create a key. A picture key is for spreadsheets. An All routes key is for your own code.

  2. Look up a value

    Send the value. The answer names the barcode type and the address of its picture, without drawing it.

    curl -H "Authorization: Bearer $BEEPABLE_KEY" \
      "https://beepable.app/b/auto.json?v=4006381333931"
    {
      "ok": true,
      "symbology": "ean13",
      "digitalLink": false,
      "imageUrl": "https://beepable.app/b/ean13.png?v=4006381333931",
      "print": {
        "minMm": 29.832,
        "targetMm": 37.29,
        "maxMm": 74.58,
        "note": "EAN-13 nominal size is 37.29 × 25.93 mm at 100%. Magnification is 80–200%."
      }
    }
    const response = await fetch("https://beepable.app/b/auto.json?v=4006381333931", {
      headers: { Authorization: `Bearer ${process.env.BEEPABLE_KEY}` },
    });
    const result = await response.json();
    if (result.ok) console.log(result.symbology, result.imageUrl);
    else console.log(result.error.code, result.error.message);
    import os, requests
    
    response = requests.get(
        "https://beepable.app/b/auto.json",
        params={"v": "4006381333931"},
        headers={"Authorization": f"Bearer {os.environ['BEEPABLE_KEY']}"},
    )
    result = response.json()
    print(result["imageUrl"] if result["ok"] else result["error"]["message"])
  3. Show the picture

    Add a picture key as k and use the address anywhere an image goes.

    <img src="https://beepable.app/b/ean13.png?v=4006381333931&k=PICTURE_KEY" alt="EAN-13 4006381333931">
    =IMAGE("https://beepable.app/i/auto.png?v="&ENCODEURL(A2)&"&k="&$Z$1)

Keys

Create keys under Account. A key is shown once. A revoked key stops working on the next request.

KeySend it asOpens
Picture key
For spreadsheets, documents, and web pages
k in the addressPictures: /i/, /b/{symbology}.png, /i/dl.png, /dl/pack.zip, /l/fnsku.png, /l/fnsku.pdf
All routes key
For your own server
Authorization: BearerEvery route, including /b/{symbology}.json, /excel, /sheets, /api/batch, /csv, /dl.json, /dl.csv, and /labels/
  • Never put an All routes key in an image address. The address is public, and a CDN may keep it for a year.
  • A picture key on a route that needs an All routes key is HTTP 403: This key can only draw pictures.
  • A pictureKey or pk that adds a key to the addresses must be a picture key of the same account. An All routes key there is HTTP 400: Use a picture key, not an All routes key, in image addresses.
  • A missing or unknown key is HTTP 401: This request needs an API key. A revoked key is: This API key has been revoked. On a picture route for a sheet, both are a PNG card instead.
  • A request with k can be cached publicly when it succeeds. A request with only Authorization is private, no-store.

Endpoints

Open an endpoint to see its parameters and responses. Choose Authorize, paste a key, and use Try it out to call it from this page. The key stays in this browser tab: it is not saved, and it is gone when you reload.

Barcodes

One value in, one barcode or one decision out.

  • GET/i/{symbology}.pngDraw a picture for a spreadsheet cell
  • GET/b/{symbology}.pngDraw a picture
  • GET/b/{symbology}.jsonLook up a value: barcode type and image address

Spreadsheets

Text routes for Excel and Google Sheets. Most sheets need only the picture route, /i/{symbology}.png.

  • GET/excelGet the image address as text (Excel WEBSERVICE)
  • GET/sheetsGet the image address as text (Apps Script)
  • GET/sheets/barcode.gsGet the Apps Script sourceNo key

Files and batches

Up to 10,000 values per request. These return addresses, not pictures.

  • POST/api/batchLook up to 10,000 values
  • POST/csvAdd image addresses to a CSV

Build a GS1 Digital Link from a GTIN, then draw its QR code.

  • GET/dl.jsonBuild a GS1 Digital Link
  • GET/i/dl.pngDraw the QR code of a Digital Link
  • GET/dl/pack.zipDownload the retail barcode and the QR code
  • POST/dl.csvBuild Digital Links for a CSV

Amazon FNSKU labels

Print-ready Code 128 labels with the FNSKU, title, and condition.

  • GET/l/fnsku.pngDraw one FNSKU label
  • GET/l/fnsku.pdfPrint copies of one label as a PDF
  • POST/labels/fnsku.pdfPrint labels from a file
  • POST/labels/fnsku.csvCheck a label file and add label addresses

Reference

Open routes that need no key.

  • GET/apiList the routesNo key
  • GET/openapi.jsonGet this OpenAPI documentNo key
  • GET/sample/{file}Get an open sample pictureNo key

Symbology names

Automatic mode accepts a valid GTIN-8, GTIN-12, GTIN-13, or GTIN-14, or an http or https URL. A 14-digit value with a leading zero stays ITF-14. An ISBN-13 stays EAN-13. A named retail symbology that does not fit is an error. The service does not switch to another symbology.

NameAccepts
autoChoose from the value.
ean88 digits and a valid check digit.
upca12 digits and a valid check digit.
ean1313 digits and a valid check digit.
itf1414 digits and a valid check digit.
code128Basic Latin, at most 500 characters. A code point above 127 is rejected.
qrAny non-empty value within 2,000 characters, including a bad GTIN.
datamatrixSame as QR. Name it for a plain Data Matrix used inside a plant. It is not the retail checkout carrier.
gs1datamatrixA parenthesised element string that starts with (01) and a 14-digit GTIN. Dates are (15) and (17) as YYMMDD. Lot, serial, and CPV are (10), (21), and (22). Other application identifiers are refused.
fnskuAn Amazon FNSKU. Automatic mode accepts 10 characters starting with X00. Named fnsku also accepts a B0 ASIN or an ISBN-10 shape.

A Digital Link is two neighbouring path segments, on any host, after any prefix. The match uses the decoded segments. /8003/00952012345678 is a GRAI. /8003/10952012345678 is not, so that URL stays a QR code. Query-string keys stay a QR code. A bad check digit inside a pasted link is bad_check_digit_in_link. Build a link from a GTIN at /digital-link.

Errors

These sentences are exact. A JSON failure uses the code and the sentence. A text or file route sends the sentence as the whole body. A picture route for a sheet draws the sentence on a PNG card. Show the message to the person who entered the value. Two codes, wrong_length and bad_check_digit, are also used by the Digital Link builder with its own sentence, so branch on the code and display the message you received.

CodeSentence
emptyEnter a GTIN or a URL.
too_longValue is longer than 2,000 characters.
not_gtin_or_urlThis is neither a valid GTIN, an Amazon FNSKU, nor a URL. Name a symbology, such as code128.
not_fnskuAn Amazon FNSKU has 10 characters and usually starts with X00. Copy it from Seller Central.
wrong_lengthA retail barcode needs 8, 12, 13, or 14 digits. This has {n}. Name code128 to encode it anyway.
bad_check_digitCheck digit is invalid for this GTIN. Name code128 to encode it anyway.
bad_check_digit_in_linkThe GS1 identifier in this Digital Link has an invalid check digit. Name qr to encode the URL anyway.
symbology_mismatch{Name} needs {n} digits. This has {count}.
unsupported_charactersCode 128 can only encode basic Latin characters.
cannot_encodeCode 128 can encode at most 500 characters.
unknown_symbologyUnknown symbology. Use auto, ean8, upca, ean13, itf14, code128, qr, datamatrix, gs1datamatrix, or fnsku.
bad_element_stringThe element string must start with (01) and a 14-digit GTIN, and use only the AIs this service checks.
bad_domainThe domain must be an https address, such as https://id.brand.com.
wrong_length (Digital Link)A GTIN needs 8, 12, 13, or 14 digits. This has {n}.
bad_check_digit (Digital Link)The check digit is invalid for this GTIN.
bad_lotThe lot must be 1 to 20 characters from GS1 character set 82. Use digits, letters, and !"%&'()*+,-./:;<=>?_.
bad_serialThe serial must be 1 to 20 characters from GS1 character set 82. Use digits, letters, and !"%&'()*+,-./:;<=>?_.
bad_cpvThe CPV must be 1 to 20 characters from GS1 character set 82. Use digits, letters, and !"%&'()*+,-./:;<=>?_.
bad_dateThe date must be YYMMDD or YYYY-MM-DD. Use a month from 01 to 12. The day may be 00.
unauthorizedThis request needs an API key. A revoked key uses: This API key has been revoked.
forbiddenThis key can only draw pictures.
rate_limitedToo many requests. Try again shortly. An upload can also answer: Too many uploads. Try again in a minute. Or: Another file is still being processed. Wait for it to finish.

Label and file sentences

CaseSentence
FNSKUAn Amazon FNSKU has 10 characters and usually starts with X00. Copy it from Seller Central.
ConditionUnknown condition. Use New, Used - Like New, Used - Very Good, Used - Good, Used - Acceptable, Collectible, or Refurbished.
QuantityQuantity must be a whole number from 1 to 1,000.
TitleThe title is longer than 500 characters.
Title textThe title must be text.
Label widthA 10-character FNSKU does not fit on this label.
TemplateUnknown label template. Use avery-5160, thermal-2x1, thermal-2.25x1.25, a4-21-63x38, a4-24-63x34, or a4-24-70x37.
StartStart must be a whole number from 1 to {n}, where {n} is the number of labels on one sheet, such as 30 for Avery 5160. A roll has no start position: Start must be a whole number from 1.
Label CSVThe CSV needs an fnsku column.
No rowsThe file has no label rows.
Label JSONThe JSON needs an items array.
Bad rowThis row is not a label.
All failedEvery row failed. Fix the FNSKU, condition, or quantity and try again.
Barcode CSVThe CSV needs a value column.
Digital Link CSVThe CSV needs a gtin column.
BatchThe request needs an items array.

Any method other than GET on a /b/ or /i/ route is HTTP 405. The renderer draws at most 32 pictures at a time. Up to 10,000 further misses wait. A miss that cannot enter that queue, or that has waited 60 seconds, is HTTP 429 with rate_limited. There is no per-address cap.

Limits

Limits are buckets that refill over time, so a short burst is fine. Pictures, decisions, and uploads are counted per account, never per network address, because Excel and Google Sheets fetch pictures from shared addresses. Only a picture that has to be drawn counts. A picture served from the cache is free, so reloading a sheet costs nothing.

Rate limits

WhatLimit
Pictures that have to be drawn20,000 per account at once, refilled at 300 per second. A sheet of 10,000 new barcodes fits in one burst.
Decisions, Excel, and Sheets text routes20,000 per account at once, refilled at 300 per second.
CSV and batch uploads30 per minute per account, and at most 2 at the same time.
Requests without a working key60 per minute per network address, except on picture routes, which always draw the key card.
Pages300 at once per network address, refilled at 10 per second.
Sign in10 failed attempts per email and 30 per network address in 15 minutes. The sentence is: Too many sign-in attempts. Try again in 15 minutes.
Password reset3 requests per email and 10 per network address in an hour. The sentence is: Too many reset requests. Check your inbox, or try again in an hour. Over the daily mail budget, the sentence is: We could not send the email right now. Try again later.
New accounts5 per hour and 20 per day per network address. The sentence is: Too many new accounts from this network. Try again later.
New keys20 per account per day. The sentence is: You have created many keys today. Try again tomorrow.
Printed labels50,000 labels per account per day. The sentence is: You have reached today's limit of 50,000 labels.

A limited request is HTTP 429 with Retry-After in seconds and Cache-Control: no-store. It also carries RateLimit-Policy and RateLimit from the IETF draft, for example RateLimit-Policy: "render";q=20000;w=67 and RateLimit: "render";r=0;t=67. A successful upload carries the same two fields. Wait for Retry-After before you try again.

Size limits

These sentences are exact. A body over the limit is refused before it is read. A form error is HTTP 400. A body over the limit is HTTP 413. An address over the limit is HTTP 414.

WhatSentence
File uploadThis file is larger than 5 MB. Split it into smaller files.
Batch bodyThis request is larger than 2 MB. Send fewer items per request.
Form bodyThis form is too large.
AddressThis address is too long.
CSV columnsA CSV can contain at most 100 columns.
CSV cellRow {n} has a cell longer than 4,096 characters.
CSV rowsA CSV can contain at most 10,000 rows.
Batch itemsA request can contain at most 10,000 items.
Label jobA label job can contain at most 10,000 labels.
Processing timeThis file took too long to process. Split it into smaller files.

Account and sign-in

These apply to the Account pages, not to API calls.

WhatSentence
EmailEnter a valid email address.
PasswordUse between 8 and 256 characters for the password.
Key nameUse at most 100 characters for the key name.
Active keysYou have 50 active keys. Revoke one before you create another.
MailWe could not send the email right now. Try again later.

One account keeps 20 sessions. A new sign-in deletes the oldest. The server closes a slow connection after 10 seconds for headers, 30 seconds for the whole request, and 5 seconds of idle keep-alive. The process keeps at most 10,000 successful responses and at most 256 MB of them, and drops the oldest. Those four have no sentence.

Retries

StatusWhat to do
429Wait the number of seconds in Retry-After, then send the same request again. Do not retry sooner.
503 on a file or label jobThe job took too long. Split the file into smaller files and send them one after another.
413 or 414The body or the address is too large. Send fewer items per request, or a smaller file.
400Do not retry. Fix the value or the request, using the code and the sentence.
401 or 403Do not retry. Use a working key of the right type.
500Retry once after a few seconds. If it fails again, contact us with the time of the request.

Uploads run at most two at a time per account. Send files one after another rather than in parallel.

Caching and CORS

Successful JSON and PNG responses with k in the address use Cache-Control: public, max-age=31536000, immutable. Without k, they are private, no-store. Errors, the batch, the CSV, and formula failures use no-store. This process also keeps the last 10,000 successful responses. GET https://beepable.app/api lists the paths, and GET https://beepable.app/openapi.json describes them.

A browser on another origin can call these routes. Access-Control-Allow-Origin is *. An OPTIONS preflight is HTTP 204.

Stability

The routes, parameters, response fields, and error codes on this page are stable. New fields and new routes may be added, so ignore fields you do not know. A field, a route, or an error code will not be removed or renamed without notice on this page and in /openapi.json, whose version number changes with every published change. The same notice applies to an error sentence. In your code, branch on the error code and show the sentence to people.

Questions

Do I need an API key?

Yes, for a barcode, a batch, or a CSV. Sign in and create a key. A picture key draws pictures in a sheet. Put it in Z1. The value is still part of the image address, so do not send a private URL.

Which key goes where?

A picture key goes in the k parameter of an image address. An All routes key goes in Authorization: Bearer, from your own server. Never put an All routes key in an image address, because that address is public.

What image format comes back?

PNG. There is no SVG on these routes. A successful picture with k in the address uses Cache-Control public, max-age=31536000, immutable.

Does a bad check digit still return a barcode?

No. The JSON error code is bad_check_digit and the sentence is: Check digit is invalid for this GTIN. Name code128 to encode it anyway.