Developer Reference
API Reference
Generate production-ready PDF417 barcodes via a single POST endpoint. Parse a US or Canadian driver's-license PDF417 into clean JSON with one call, including privacy-safe age and expiry checks when `redactPII` is enabled.
Quickstart
No API key required for development. Send a JSON POST to /api/generate with a payload field:
curl -sS -X POST http://127.0.0.1:5055/api/generate \
-H "Content-Type: application/json" \
-d '{"payload": "HELLO PDF417"}' \
| python3 -m json.tool
Decode the base64 PNG and save to disk:
curl -sS -X POST http://127.0.0.1:5055/api/generate \
-H "Content-Type: application/json" \
-d '{"payload": "HELLO PDF417"}' \
| python3 -c "
import sys, json, base64
data = json.load(sys.stdin)
open('barcode.png', 'wb').write(base64.b64decode(data['pngBase64']))
print('Saved barcode.png')
"
Endpoint
/api/generate
Accepts Content-Type: application/json. Returns application/json. Maximum request body: 512 KB.
Request schema
All fields except payload are optional and fall back to the listed defaults.
| Field | Type | Default | Range | Description |
|---|---|---|---|---|
payload required |
string | — | 1–20,000 chars | The text or data string to encode into the barcode symbol. |
columns |
integer | 6 |
1–30 | Number of data columns. More columns = wider barcode and fewer rows. |
errorCorrection |
integer | 2 |
0–8 | PDF417 error correction level. Higher values add redundancy and increase symbol size. Level 2 is suitable for most print use cases. |
moduleWidth |
integer | 3 |
1–50 | Width of the narrowest bar or space in pixels. Increase for larger print dimensions. |
rowHeight |
integer | 9 |
1–200 | Height of each row in pixels. ISO/IEC 15438 recommends a minimum row height of 3× module width for reliable scanning. |
padding |
integer | 20 |
0–500 | Quiet zone padding in pixels applied uniformly to all four sides. |
foreground |
string | #000000 |
CSS hex | Bar color as a CSS hex string. Must provide sufficient contrast with the background for reliable scanning. |
background |
string | #FFFFFF |
CSS hex or transparent |
Space color as a CSS hex string. Use transparent for a transparent PNG with RGBA channel output. |
standard |
string | pdf417 |
pdf417 |
Barcode standard. Only pdf417 (ISO/IEC 15438) is currently supported. |
Full request example
{
"payload": "SHIPMENT-001\nDEST: WAREHOUSE-B\nSKU: 4921-AX",
"columns": 6,
"errorCorrection": 2,
"moduleWidth": 3,
"rowHeight": 9,
"padding": 20,
"foreground": "#000000",
"background": "transparent"
}
Response schema
Successful responses return HTTP 200 with the following JSON body:
{
"pngBase64": "iVBORw0KGgoAAAANSUhEUg...",
"info": {
"standard": "PDF417 (ISO/IEC 15438)",
"columns": 6,
"rows": 3,
"moduleWidth": 3,
"rowHeight": 9,
"errorCorrectionLevel": 2,
"errorCorrectionCodewords": 8,
"padding": 20,
"moduleSize": { "width": 171, "height": 3 },
"imageSize": { "width": 553, "height": 67 },
"bytes": 618,
"mode": "RGBA"
}
}
| Field | Type | Description |
|---|---|---|
pngBase64 |
string | Base64-encoded PNG image bytes. Decode with base64.b64decode() or equivalent. |
info.rows |
integer | Number of rows in the generated symbol. |
info.columns |
integer | Number of data columns used. |
info.errorCorrectionLevel |
integer | Error correction level applied (0–8). |
info.errorCorrectionCodewords |
integer | Number of error-correction codewords implied by the selected level. |
info.moduleSize |
object | Barcode symbol size before pixel scaling and padding. |
info.imageSize |
object | Output PNG dimensions as width and height. |
info.bytes |
integer | PNG file size in bytes. |
info.mode |
string | RGBA when background is transparent; RGB otherwise. |
Response headers
| Header | Description |
|---|---|
X-RateLimit-Limit |
Maximum requests allowed per window. |
X-RateLimit-Remaining |
Requests remaining in the current window. |
Retry-After |
Seconds to wait before retrying. Present only on 429 responses. |
Error codes
| HTTP status | Error | Cause |
|---|---|---|
400 |
Payload is required. |
The payload field was missing or empty. |
400 |
Payload must be 20000 characters or less. |
Payload exceeds the 20,000-character limit. |
400 |
<field> must be an integer. |
A numeric parameter was supplied as a non-integer. |
400 |
<field> must be at least <n>. |
A parameter was below the allowed minimum. |
400 |
<field> must be at most <n>. |
A parameter exceeded the allowed maximum. |
413 |
Request body too large | The request body exceeded 512 KB. |
429 |
Rate limit exceeded. |
Too many requests from this IP in the current window. Check Retry-After. |
Error response body
// HTTP 400
{ "error": "Payload is required." }
// HTTP 429
{
"error": "Rate limit exceeded.",
"limit": 60,
"windowSeconds": 60,
"retryAfterSeconds": 14
}
Rate limits
The API applies a sliding-window rate limit keyed by client IP address. When the limit is exceeded the server responds with HTTP 429 and a Retry-After header.
| Setting | Default | Override via |
|---|---|---|
| Max requests per window | 60 | PDF417_RATE_LIMIT_MAX_REQUESTS |
| Window duration | 60 seconds | PDF417_RATE_LIMIT_WINDOW_SECONDS |
API plan customers will have higher limits enforced via API key in a future release.
Code examples
cURL
# Basic generation — save PNG to disk
curl -sS -X POST http://127.0.0.1:5055/api/generate \
-H "Content-Type: application/json" \
-d '{
"payload": "ORDER-9821\nSKU: XR-440\nQTY: 12",
"columns": 6,
"errorCorrection": 2,
"moduleWidth": 3,
"rowHeight": 9,
"padding": 20
}' | python3 -c "
import sys, json, base64
d = json.load(sys.stdin)
open('barcode.png','wb').write(base64.b64decode(d['pngBase64']))
print('rows:', d['info']['rows'], '| size:', d['info']['imageSize']['width'], 'x', d['info']['imageSize']['height'])
"
# Transparent background (RGBA PNG)
curl -sS -X POST http://127.0.0.1:5055/api/generate \
-H "Content-Type: application/json" \
-d '{"payload": "TICKET-EVENT-2026", "background": "transparent"}' \
| python3 -c "
import sys, json, base64
open('ticket.png','wb').write(base64.b64decode(json.load(sys.stdin)['pngBase64']))
print('Saved ticket.png')
"
Python
import requests, base64
from pathlib import Path
API_URL = "http://127.0.0.1:5055/api/generate"
def generate_barcode(payload, *, output="barcode.png", **kwargs):
"""Generate a PDF417 barcode PNG and save it to disk."""
resp = requests.post(
API_URL,
json={"payload": payload, **kwargs},
timeout=15,
)
resp.raise_for_status()
data = resp.json()
Path(output).write_bytes(base64.b64decode(data["pngBase64"]))
return data["info"]
# Basic
info = generate_barcode("SHIPMENT-001\nDEST: WAREHOUSE-B", output="shipment.png")
print(f"Generated: {info['imageSize']['width']}x{info['imageSize']['height']}px, {info['rows']} rows")
# Transparent PNG
info = generate_barcode("TICKET-EVENT-2026", background="transparent", output="ticket.png")
print(f"Mode: {info['mode']}") # RGBA
# Batch from list
for i, item in enumerate(["ORDER-001", "ORDER-002", "ORDER-003"]):
generate_barcode(item, output=f"barcode_{i:04d}.png")
print(f"Saved barcode_{i:04d}.png")
JavaScript (fetch)
const API_URL = 'http://127.0.0.1:5055/api/generate';
async function generateBarcode({ payload, columns = 6, errorCorrection = 2,
moduleWidth = 3, rowHeight = 9, padding = 20, background = '#FFFFFF' }) {
const resp = await fetch(API_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ payload, columns, errorCorrection,
moduleWidth, rowHeight, padding, background }),
});
if (!resp.ok) {
const err = await resp.json().catch(() => ({}));
throw new Error(err.error ?? `HTTP ${resp.status}`);
}
return resp.json();
}
// Display in an <img> element
generateBarcode({ payload: 'HELLO PDF417', background: 'transparent' })
.then(({ pngBase64, info }) => {
const img = document.getElementById('barcode-preview');
img.src = `data:image/png;base64,${pngBase64}`;
console.log(`Generated: ${info.imageSize.width}x${info.imageSize.height}`);
})
.catch(console.error);
// Node.js — save to disk
import { writeFileSync } from 'node:fs';
const { pngBase64 } = await generateBarcode({ payload: 'NODE-BATCH-001' });
writeFileSync('barcode.png', Buffer.from(pngBase64, 'base64'));
console.log('Saved barcode.png');
Authentication
The current public API does not require authentication. API key-based auth will be introduced with the paid API plan. When active, pass your key in the Authorization header:
Authorization: Bearer pdf417_live_xxxxxxxxxxxxxxxxxxxx
Development and free-tier usage continues without a key, subject to IP-based rate limits.
AAMVA parser
Parse a US or Canadian driver's-license PDF417 into clean JSON with one call. Header, subfiles, date formats, and validation are handled for you. Use redactPII to age-gate without touching personal data.
Most ID-scanning flows only need the answer to a narrow question: is this person of age, and is the license still valid? The paid AAMVA parser is positioned to return is21Plus, isExpired, and ageYears while masking personal fields.
Pricing & limits
The free public API is subject to IP-based rate limits. For higher volume, batch generation, SVG output, API keys, AAMVA parsing, and usage dashboards, see the paid plans.
View pricing → Need self-hosted deployment? → Preview security package →