Qrop logoQrop

Choosing an error correction level for high-volume automated generation

By Qrop Team ·

Our guide on error correction levels covers what L, M, Q, and H mean for a single code you're designing by hand. Automated generation through the API is a different problem: nobody is looking at each code before it ships, so the level has to be decided once, correctly, for the whole run, based on how the codes will actually be printed or displayed downstream rather than on a case-by-case look.

This guide is about that upfront decision: what the errorCorrection parameter on POST /api/v1/generate actually costs you at volume, why POST /api/v1/generate/batch doesn't expose it as a parameter at all, and how to pick a default for a pipeline rather than a single request.

The single-call parameter

POST /api/v1/generate accepts an optional errorCorrection field set to L, M, Q, or H. Leave it out and Qrop defaults to M, the same balanced default as the web generator. Set logoUrl or logoDataUrl on the same request and the level is silently upgraded to H regardless of what you passed, since a logo needs the full recovery budget to stay scannable. There's no way to force a lower level alongside a logo, the API rejects that combination the same way the generator UI does.

For a single request this is a minor decision. At volume it's the one setting in your payload that determines how dense every code in the run is, which in turn affects file size, minimum safe print size, and how forgiving the codes are of whatever happens to them between generation and being scanned.

Batch generation doesn't expose this parameter

POST /api/v1/generate/batch has no errorCorrection field in its request body at all. Format, resolution, and an optional shared logo are set once for the whole batch, and the error correction level is inferred the same way as a single call without the parameter: M by default, auto-upgraded to H the moment a logo is attached to the batch.

If your pipeline needs a specific level other than that default, batch isn't the right tool for that run, use POST /api/v1/generate in a loop instead, accepting the trade-off that each item now counts as its own request against your rate limit rather than one request per 25 items. In practice this only matters for pipelines that specifically need L or Q at scale (digital-only display, or codes going onto packaging that already gets careful handling), most automated runs are perfectly served by batch's implicit M-or-H behaviour.

Why density matters more at volume than it seems to for one code

A higher error correction level packs more redundancy into the same content, which forces a larger grid (more modules) to hold it. For one code, a slightly denser grid is invisible unless you're printing very small. Across a run of 10,000 identical-format codes, that density difference compounds into two concrete costs: larger SVG and PNG file sizes (more modules means more path data or pixels to encode), and a higher minimum print size before individual modules become too small for a camera to resolve reliably.

If your pipeline writes generated files to storage or ships them to a print vendor as a batch, the file-size difference between M and H across thousands of codes is a real, measurable number, not a rounding error. Test the actual output size at your chosen resolution before committing a whole run to H when M would have been sufficient for the destination.

Picking a level for the pipeline, not the code

  • Digital-only destinations (an email, an app screen, a link-in-bio card generated on the fly): L is defensible here since there's no physical damage risk, and it keeps file size and minimum module size as small as possible across the run.
  • Packaging and labels applied by a machine at speed (one QR per SKU, printed inline on a label press): M is the safe default, the same reasoning as the generator's own default, since machine-applied labels are handled consistently and rarely take the kind of physical damage a hand-placed sticker does.
  • Codes headed for variable real-world conditions you don't control per-item, outdoor signage, vehicle decals, anything printed once and left exposed for months: set Q or H explicitly on every request rather than accepting the M default, since there's no operator reviewing each one before it goes out to catch a case that needed more headroom.
  • Any run that includes a shared logo: don't set errorCorrection at all, letting the automatic upgrade to H happen is simpler than tracking the logo-presence rule yourself, and it can't be overridden anyway.
  • If the run mixes destinations with genuinely different durability needs, split it into separate API calls per group rather than picking one level for everything, the cost of an extra loop is negligible next to reprinting a batch that used the wrong level for its actual destination.

A worked example: a packaging pipeline choosing its default once

Say a fulfilment system generates one QR code per SKU at pack time, feeding a label printer that applies the code directly onto each box as it moves down the line. The destination is consistent across the whole catalogue: machine-printed, then handled in a warehouse and during shipping, not weathered outdoors for months.

That consistency is exactly what makes this a pipeline-level decision rather than a per-code one: the integration sets errorCorrection to M once in its request template (or leaves it unset, since M is already the default) and every SKU's code inherits the same level without a conditional anywhere in the code. If a future product line needs codes applied to outdoor equipment instead, that's a genuinely different destination profile, and it gets its own template with Q or H, not a per-item override bolted onto the existing one.

Frequently asked questions

What error correction level does the API use if I don't set one?

M (Medium), the same default as the web generator. It's automatically upgraded to H whenever a logo is attached to the request, whether that's a single generate call or a batch call with a shared logo.

Can I set a different error correction level per item in a batch request?

No. POST /api/v1/generate/batch doesn't expose an errorCorrection parameter at all, every item in a batch gets the same inferred level (M, or H if the batch has a logo). If your items genuinely need different levels, generate them with separate POST /api/v1/generate calls instead.

Does a higher error correction level cost more credits?

No. Credit cost is based on the generation itself (and format, for some plans), not the error correction level. Choosing H over L doesn't change what a request costs, only the density and file size of the resulting code.

Can I force a lower error correction level when my request includes a logo?

No. Any request with logoUrl or logoDataUrl set is upgraded to H regardless of what errorCorrection value you pass, and this can't be overridden. A logo covers part of the code's surface, and only H reliably tolerates that coverage.

How do I know if M is dense enough for my print size before committing to a full run?

Generate a single test code through POST /api/v1/generate at your intended resolution and format, then print and scan it at the actual size and material your run will use, the same test methodology covered in our design guide for scannable codes. Confirm it before running the full batch, not after.

Related guides

Ready to create your QR code?

Generate a free QR code in seconds: custom colours, logos, and PNG, SVG or PDF output.

Open the generator

We use strictly necessary cookies to run Qrop, and (only with your consent) advertising cookies. See our privacy policy for details.