apyhub
Back
DATA VALIDATION · DEVELOPER TOOLS

Validate Payment & Generate QR API

What it does

QR Standards Validator checks a raw payment or GS1 payload against a selected specification, then returns the parsed fields, validity result, and any blocking errors or non-blocking warnings. Send the exact encoded payload and choose one of the supported standards: gs1-digital-link, epc-sepa, swiss-qr-bill, pix-br-code, upi, or emvco-mpm.

Use it when you need to verify a QR payload before you store it, generate it, or send it to a scanner or payment flow. The validation response includes the applied standard, a boolean valid, the exact specification version used, normalized output when a canonical form exists, structured fields parsed from the payload, plus errors and warnings for automation and debugging.

The service also renders validated payloads as scannable QR codes with POST /render. Send the same standard and payload; the two endpoints run the same checks, so a payload that fails validation is rejected with 422 invalid_payload and nothing is rendered. Rendering is plain and deterministic: format (json, png, svg, jpeg, webp, pdf), size (32–2048 px), dark and light colours. Error correction is fixed at level M and every code is scan-verified, so verified confirms the symbol decodes back to the payload. For styled codes, logos or typed content use the Scan-Checked QR & Barcode Studio API.

Use the reference fixtures endpoint, GET /fixtures, to fetch official-source payload examples for testing. That helps you compare your implementation against published samples and confirm your validator or encoder behaves as expected.

▣ ENDPOINT 01 / 03
POST
Validate one GS1 or payment QR payload
https://api.eu.apyhub.com/callable-labs/validate-standard-payload/validate

QUICKSTART

GUIDE

Quickstart

Validate a QR payment payload by sending the standard and raw encoded payload in a JSON body.

curl -X POST "https://api.eu.apyhub.com/callable-labs/validate-standard-payload/validate" \
  -H "apy-token: $APY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "standard": "gs1-digital-link",
    "payload": "https://id.gs1.org/01/09506000134352/21/ABC123"
  }'

What you'll get back

Returns a JSON object with standard and specification strings, a valid boolean, and optional errors, warnings, fields, and normalized fields. valid is true when no blocking validation errors were found.

{
  "standard": "gs1-digital-link",
  "valid": true,
  "normalized": "https://id.gs1.org/01/09506000134352/21/ABC123",
  "fields": {
    "domain": "id.gs1.org",
    "primary_ai": "01",
    "path_ais": {
      "21": "ABC123",
      "01": "09506000134352"
    },
    "query_ais": {}
  },
  "errors": [],
  "warnings": [],
  "specification": "GS1 Digital Link URI Syntax 1.7.0 (August 2026)"
}
TRY ITLIVE · 10 ATOMS
Loading your default key…
The full key is used to call the gateway and stays in this tab — never sent to orbit or saved.
body*
Complete raw payload to validate, exactly as encoded in the QR symbol or URI, 1 to 10,000 characters. Preserve newlines for EPC/SEPA and Swiss QR-bill payloads; whitespace and case are significant for most schemes.
Standard to validate the payload against. Only the selected scheme's rules run. Choose `gs1-digital-link`, `epc-sepa`, `swiss-qr-bill`, `pix-br-code`, `upi` or `emvco-mpm`.

About this endpoint

What it does

Validates a single QR payment or GS1 payload against the selected standard and returns the validation outcome, parsed fields, and any findings. The request provides the raw payload plus the standard to apply; the response reports whether it is valid and includes structured validation details.

Request Body

ParameterTypeMandatoryDescription
payloadStringYesComplete raw payload to validate, exactly as encoded in the QR symbol or URI. Length: 1 to 10,000 characters. Preserve newlines for EPC/SEPA and Swiss QR-bill payloads; whitespace and case are significant for most schemes.
standardENUMYesStandard to validate the payload against. Allowed values: gs1-digital-link, epc-sepa, swiss-qr-bill, pix-br-code, upi, emvco-mpm. Only the selected scheme's rules run.

Response

Returns a JSON object with valid as a boolean, errors and warnings as arrays of validation findings, fields as a structured object with parsed payload data, standard as a string naming the applied standard, normalized as a nullable string for the canonical payload form when available, and specification as a string identifying the public specification and version used for validation.

ParameterTypeMandatoryDescription
validBooleanYesTrue when no blocking validation errors were found. Warnings alone do not set this to false.
errorsObject ArrayNoBlocking issues that make the payload invalid. Each item contains code and message, with optional field when available.
fieldsObjectNoStructured fields parsed from the payload. Shape depends on the scheme; additional properties are allowed.
standardStringYesStandard that was applied to the payload.
warningsObject ArrayNoNon-blocking interoperability or quality findings. The payload can still be valid with warnings present.
normalizedStringNoCanonical payload representation when the standard defines one, such as a lower-cased GS1 host and scheme, LF-normalized EPC/Swiss payloads, or a re-encoded UPI query. Null when no canonical form exists.
specificationStringYesExact public specification and version used for validation.

Body

Name
Type
Description
bodyREQUIRED
object
▣ ENDPOINT 02 / 03
POST
Generate a QR code from a validated payload
https://api.eu.apyhub.com/callable-labs/validate-standard-payload/render

QUICKSTART

GUIDE

Quickstart

Encode a raw GS1 or payment payload into a QR code with the default JSON response.

curl -X POST "https://api.eu.apyhub.com/callable-labs/validate-standard-payload/render" \
  -H "apy-token: $APY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "body": {
      "standard": "gs1-digital-link",
      "payload": "https://id.gs1.org/01/09506000134352/21/ABC123",
      "format": "json"
    }
  }'

What you'll get back

Returns a JSON object containing the rendered QR code as a PNG data URI together with metadata such as format, media_type, width, height, version, content, and verified.

{
  "format": "json",
  "image_format": "png",
  "media_type": "image/png",
  "width": 328,
  "height": 328,
  "data_uri": "data:image/png;base64,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",
  "warnings": [],
  "verified": true,
  "modules": {
    "width": 33,
    "height": 33
  },
  "version": 4,
  "error": "Q",
  "micro": false,
  "designator": "4-Q",
  "content": "https://id.gs1.org/01/09506000134352/21/ABC123"
}
TRY ITLIVE · 20 ATOMS
Loading your default key…
The full key is used to call the gateway and stays in this tab — never sent to orbit or saved.
body*
Validate a complete raw payload against the named standard and, only if it passes, render it as a plain QR code. No styling and no typed-content helper: error correction is fixed at `M` and every code is scan-verified before it is returned.
Complete raw payload exactly as encoded, 1 to 10,000 characters. EPC/SEPA and Swiss QR-bill are line-delimited: separate lines with a line feed inside the JSON string. Literal `\n` sequences are decoded and reported as an `escaped_newlines` warning. The canonical form is what gets encoded: LF line endings and a lower-cased scheme/host for GS1 Digital Link.
Standard the payload must satisfy before it is rendered. Only the selected scheme's rules run, the same checks as `POST /v1/standards/validate`. If the payload fails, the response is `422 invalid_payload` with the validator's error list and nothing is rendered.
Colour of the dark modules: a hex value such as `#1d4ed8`, an `rgb()` value or a CSS colour name.
Exact output width in pixels, 32 to 2048. Omit to use eight pixels per QR module.
Background colour. Use `transparent` or null for no background; some scanners rely on a light quiet zone, so verify transparent output.

About this endpoint

What it does

Validates a complete GS1 or payment payload against the selected standard and renders it as a scannable QR code. The payload must be provided as a raw string, and the selected standard's validation rules are applied before rendering.

Request Body

ParameterTypeMandatoryDescription
standardENUMYesStandard the payload must satisfy before it is rendered. Allowed values: gs1-digital-link, epc-sepa, swiss-qr-bill, pix-br-code, upi, emvco-mpm.
payloadStringYesComplete raw payload to encode, from 1 to 10,000 characters. EPC/SEPA and Swiss QR-bill payloads are line-delimited using LF (\n). Literal \n sequences are decoded and reported with an escaped_newlines warning.
darkStringNoColour of the dark modules. Supports a hex value such as #1d4ed8, an rgb() value or a CSS colour name. Default: #000000.
lightStringNoBackground colour. Use transparent or null for no background. Default: #ffffff.
sizeIntegerNoExact output width in pixels, from 32 to 2048. Omit to use the default module-based size.
formatENUMNoOutput format. Allowed values: json, png, svg, jpeg, webp, pdf. Default: json.

Response

For format=json, returns a JSON object containing the rendered QR code as a PNG data URI together with metadata and scan-verification information.

ParameterTypeMandatoryDescription
errorStringNoQR error-correction level used for the symbol. Fixed at M (15%).
widthIntegerNoPixel width of the rendered output.
heightIntegerNoPixel height of the rendered output.
formatStringNoEchoes the requested output format. Always json for this response envelope.
contentStringNoExact canonical string written into the QR symbol.
versionIntegerNoQR symbol version (module grid size).
data_uriStringNoReady-to-embed PNG data URI for the JSON response.
verifiedBooleanNoTrue when the rendered QR code successfully decodes back to content; false when verification fails.
warningsString ArrayNoNon-blocking validation or scannability warnings.
media_typeStringNoMIME type of the returned image.
image_formatStringNoImage encoding inside data_uri. JSON output always uses png.

Notes

The payload must pass validation for the selected standard before it is rendered. If validation fails, the API returns 422 invalid_payload and nothing is rendered.

QR error correction is fixed at M. Every generated QR code is scan-verified. A failed scan check still returns 200 with verified=false and a warning.

For output formats other than json, the API returns the raw image or PDF bytes with the matching content type.

Body

Name
Type
Description
bodyREQUIRED
object
Validate a complete raw payload against the named standard and, only if it passes, render it as a plain QR code. No styling and no typed-content helper: error correction is fixed at `M` and every code is scan-verified before it is returned.
▣ ENDPOINT 03 / 03
GET
Get official-source reference fixtures
https://api.eu.apyhub.com/callable-labs/validate-standard-payload/fixtures

QUICKSTART

GUIDE

Quickstart

Fetch reference QR payment fixtures for a standard like upi or swiss-qr-bill.

curl -X GET "https://api.eu.apyhub.com/callable-labs/validate-standard-payload/fixtures?standard=upi" \
  -H "apy-token: $APY_TOKEN"

What you'll get back

Returns a JSON array of fixture objects. Each object includes id, standard, title, payload, source, and note fields, and may also include expected_valid to indicate the validator should accept the payload.

[
  {
    "id": "upi-pay-basic",
    "standard": "upi",
    "title": "UPI pay deep link",
    "payload": "upi://pay?pa=callablelabs@upi&pn=Callable%20Labs&am=10.00&cu=INR&tn=API%20test",
    "expected_valid": true,
    "source": "https://www.npci.org.in/PDF/npci/upi/circular/2017/Circular%20on%20Non-compliance%20of%20UPI%20apps%20to%20Deeplinking%20specs%20Circular%2037-%201.11.2017.pdf",
    "note": "Conformance fixture derived from NPCI UPI Deep Linking 1.5.1 requirements."
  }
]
TRY ITLIVE · 1 ATOM
Loading your default key…
The full key is used to call the gateway and stays in this tab — never sent to orbit or saved.

About this endpoint

What it does

Returns a list of official-source reference fixtures for the requested QR payment standard. Each item is a JSON object containing a fixture identifier, descriptive metadata, the source URI, the payload to submit unchanged, and the standard it represents.

Query Parameter(s)

AttributeTypeMandatoryDescription
standardENUMNoStandard to filter fixtures by. Allowed values: gs1-digital-link, epc-sepa, swiss-qr-bill, pix-br-code, upi, emvco-mpm.

Response

Returns a JSON array of objects. Each object includes id, standard, title, payload, source, and note fields, and may also include expected_valid to indicate the validator result expected for that fixture.

ParameterTypeMandatoryDescription
[]Object ArrayYesArray of fixture objects derived from official public specifications.
[ ].idStringYesStable fixture identifier you can reference in tests, e.g. swiss-qr-bill-qrr.
[ ].standardStringYesStandard represented by the fixture.
[ ].titleStringYesShort human-readable description of what the fixture contains.
[ ].payloadStringYesComplete payload, ready to submit unchanged to POST /v1/standards/validate.
[ ].sourceStringYesOfficial public specification or sample page the fixture was derived from.
[ ].noteStringYesProvenance or interpretation note describing how the fixture was assembled.
[ ].expected_validBooleanNoResult the validator should return when the payload is submitted. Defaults to true. True for every published fixture today.

Query parameters

Name
Type
Description
standardOPTIONAL
string
gs1-digital-link · epc-sepa · swiss-qr-bill · pix-br-code · upi · …
▣ COMMON ERRORS

Errors any endpoint can return

400bad_request

Required parameter missing or malformed body.

401unauthorized

API key missing, revoked, or not authorized for this service.

429rate_limited

Your plan's per-second rate exceeded. Retry with exponential backoff.

503upstream_busy

Backend temporarily unavailable. Try again in a few seconds.