QR & Barcode / TUTORIAL

Generate, decode and validate a QR code

Create a QR image, decode it back to text and check a structured payload before distributing it.

This guide describes production API usage. The website demo has a separate, smaller anonymous allowance. Subscribe to an available listing before running the scripts.

Choose your marketplace

The complete scripts below target RapidAPI. Use the provider tabs for the matching base URL and authentication pattern; ApyHub capabilities may be split across listings and remain unavailable until published. Never use a pending listing as a production endpoint.

import os
import httpx

base_url = "https://qr-barcode-api-generate-style-decode-validate.p.rapidapi.com"
headers = {
    "X-RapidAPI-Key": os.environ["RAPIDAPI_KEY"],
    "X-RapidAPI-Host": "qr-barcode-api-generate-style-decode-validate.p.rapidapi.com",
}
payload = {
    "data": "https://example.com",
    "options": {
        "format": "png",
        "size": 384,
    },
}
response = httpx.post(
    base_url + "/v1/generate",
    headers=headers, json=payload, timeout=120
)
response.raise_for_status()
with open("result.png", "wb") as output:
    output.write(response.content)

This tutorial exercises a complete QR workflow: generate a code, decode the rendered image, then validate structured content against a published standard. All three endpoints are available on the BASIC plan.

Before you start

Subscribe to the API and export the host and key shown by RapidAPI:

export RAPIDAPI_HOST='qr-barcode-api-generate-style-decode-validate.p.rapidapi.com'
export RAPIDAPI_KEY='your-key-from-rapidapi'

1. Generate a QR code as JSON

curl --fail-with-body --max-time 45 --request POST \
  --url "https://${RAPIDAPI_HOST}/v1/generate" \
  --header 'content-type: application/json' \
  --header "x-rapidapi-host: ${RAPIDAPI_HOST}" \
  --header "x-rapidapi-key: ${RAPIDAPI_KEY}" \
  --data '{"data":"https://example.com/orders/1042"}' \
  --output generated.json

The file contains a base64 data_uri plus the generated QR metadata.

2. Decode the generated image

If jq is installed, build the decode request without copying the long data URI:

jq '{image_base64: .data_uri, formats: ["qr"], multiple: false}' \
  generated.json | tee decode-request.json

curl --fail-with-body --max-time 45 --request POST \
  --url "https://${RAPIDAPI_HOST}/v1/decode" \
  --header 'content-type: application/json' \
  --header "x-rapidapi-host: ${RAPIDAPI_HOST}" \
  --header "x-rapidapi-key: ${RAPIDAPI_KEY}" \
  --data @decode-request.json

The response lists the detected symbol, decoded text, position and orientation. For recognized typed content it also includes parsed fields. Confirm that the decoded text is https://example.com/orders/1042 before distributing the code.

For an existing image, send either image_base64 or a public image_url, but not both. Decode accepts images up to 5 MB and 24 megapixels.

3. Validate a GS1 Digital Link payload

Generation and decoding prove that pixels can round-trip. Standards validation answers a different question: whether structured content follows the selected specification.

curl --fail-with-body --max-time 45 --request POST \
  --url "https://${RAPIDAPI_HOST}/v1/standards/validate" \
  --header 'content-type: application/json' \
  --header "x-rapidapi-host: ${RAPIDAPI_HOST}" \
  --header "x-rapidapi-key: ${RAPIDAPI_KEY}" \
  --data '{
    "standard": "gs1-digital-link",
    "payload": "https://id.gs1.org/01/09520123456788/10/ABC123"
  }'

Inspect valid, fields, errors and warnings. An invalid result is still a successful API response: it means the validator processed the payload and found specification problems.

Supported standards are gs1-digital-link, epc-sepa, swiss-qr-bill, pix-br-code, upi and emvco-mpm. Use GET /v1/standards/fixtures for known-good and known-bad reference payloads.

Validation is deterministic conformance checking, not certification by a payment scheme or standards body.

Complete Python example

Requires Python 3.10+ and requests (python -m pip install requests). Save as qr_example.py and run python qr_example.py after setting RAPIDAPI_KEY. The order URL is fictitious; protect any sensitive content and generated QR files.

import base64
import os
from pathlib import Path

import requests

HOST = "qr-barcode-api-generate-style-decode-validate.p.rapidapi.com"
HEADERS = {"x-rapidapi-host": HOST, "x-rapidapi-key": os.environ["RAPIDAPI_KEY"]}
payload = {'data': 'https://example.com/orders/1042'}
response = requests.post(f"https://{HOST}/v1/generate", headers=HEADERS, json=payload, timeout=45)
response.raise_for_status()
result = response.json()
encoded = result["data_uri"].split(",", 1)[1]
Path("qr.png").write_bytes(base64.b64decode(encoded, validate=True))
decoded = requests.post(
    f"https://{HOST}/v1/decode", headers=HEADERS,
    json={"image_base64": result["data_uri"], "formats": ["qr"], "multiple": False},
    timeout=45,
)
decoded.raise_for_status()
print(decoded.json())
print("saved qr.png")

Errors, pacing and allowance

Check the HTTP status before using a response file. Fix 422 request errors; a 403 plan_excludes_feature needs a plan that includes the feature. Retry temporary 429/502/503/504 responses only with a bounded delay, honoring Retry-After. Monthly quota exhaustion cannot be fixed with retries. Each call, including a separate decode or validation step and retries, may consume allowance. Keep within your current plan’s rate limit. A 45-second client timeout is a finite client budget, not a service-latency guarantee. See the Developer guide and Privacy Notice.

Make it part of your application.

Get credentials and a production allowance from an available marketplace.

RRapidAPI
Complete APIGet access
aApyHub
Generate QR codes & barcodesAvailability pending