Automating QR Code Creation With APIs and Automation Tools — featured illustration
Technology

Automating QR Code Creation With APIs and Automation Tools

6 min read
Create a QR code

A ticketing coordinator opens a spreadsheet of 2,300 registrations at eleven at night and starts pasting URLs into a generator one row at a time. Somewhere around row sixty the mistakes begin: a skipped line, a duplicated file name, a code saved over another. Nothing about that job was hard. It was just too long to do by hand, and it will be exactly as long again next month.

That is the shape of the problem automation solves. Not "we make a lot of codes," but "we make one code per record, and records keep arriving."

When automation earns its keep

Build automation when a code belongs to a thing rather than to a campaign. One per order. One per asset tag, rental unit, table, shipment, or event registration. The tell is that the count grows with the business, not with the marketing calendar.

The second tell is timing. The code has to exist at a moment nobody can schedule: an order placed at 3am that needs a packing slip, a device pulled from a box and provisioned on site. If no human is sitting at a browser at that moment, generation has to hang off an event.

If neither is true, skip the integration. A few hundred codes made once, from a list you already have, is a job for a bulk generator and a CSV: upload a column of destinations, download a folder of images, done before lunch, with nothing left to maintain. Plenty of teams build a pipeline for work that happens twice a year.

The shape of a generation request

Vendors differ in naming and detail, so treat this as general anatomy rather than anyone's actual contract. Read the documentation for the service you pick.

Going in:

  • The payload. What gets encoded: a URL, a phone number, Wi-Fi credentials, a contact card. The only genuinely required input.
  • Appearance. Foreground and background colors, module shape, logo, margin, and error correction level. The four levels recover roughly 7, 15, 25, and 30 percent of a damaged symbol, low to high.
  • Output. Format and dimensions. Raster for screens; vector if anything downstream goes to a printer.
  • Metadata. A name, a folder, a campaign label. Uninteresting until code number 8,000, at which point it is the only way to find code number 12.

Coming back, you will usually see one of three things: raw image bytes, a JSON body with the image encoded as a string, or a JSON body pointing at a hosted file you fetch in a second call. The third is where people get burned, because the response arrives fast and the image download can still fail later.

Generating an image is not the same as creating a code

Two operations get filed under one heading and they behave nothing alike.

Generating a static code is close to a pure function. A destination goes in, an image comes out, nothing is stored on the vendor's side, and running it twice produces the same picture. Lose the file and you regenerate it. There is no record to leak, break, or pay for.

Creating a dynamic code is a write. A record now exists somewhere: an identifier, a short redirect URL, a current destination, and a growing pile of scan events you can read as analytics. Because it is a write, it can half-fail, it can be duplicated, and it has to be cleaned up when the thing it points at goes away. Every hard part of automating QR codes traces back to this distinction.

Idempotency, or the night one webhook made forty codes

Here is the failure that eventually shows up in all of these integrations. A payment provider fires an order-created webhook. Your handler calls the QR API, gets a code back, then times out writing to your own database and never returns a 200. The provider retries. Five minutes later that order has six dynamic codes, five of them orphaned and all counting against your plan.

Three defenses, in order of how much they help:

  • Key the operation on your own record. A unique constraint on order ID in whatever table holds the code reference is the cheapest correctness you will ever buy.
  • Check before you create. Look up the existing code for that record and return it instead of minting another. It also makes replays safe.
  • Send an idempotency key if the API accepts one. Derive it deterministically from your record ID, never from a timestamp or a random value, or the retry generates a fresh key and defeats the purpose.

Write the code reference into your database in the same transaction that marks the job complete. If those two can drift apart, they will.

Rate limits, batching, and the backfill that trips them

Steady-state traffic is rarely the problem. One code per order is a trickle. The backfill is the problem: the afternoon someone decides all 40,000 existing assets need codes and fires the whole list at once.

Read the published limits for the service instead of guessing at them, then build for the general case anyway. A queue rather than a loop. A cap on concurrent requests. Exponential backoff with jitter on any 429 or 5xx. A resumable job, so a crash at item 19,000 does not restart at item one. If the vendor offers a batch endpoint, use it; one request for 500 codes beats 500 requests in every dimension, including your logs.

Spread large backfills across hours. Nothing about a five-year-old asset requires its code to exist within the next nine minutes.

Save the identifier, not just the picture

The image is the least valuable thing in the response. Store, alongside your own record: the vendor's code identifier, the short URL, the destination as of creation, and the creation timestamp.

That row is what lets you repoint a code when the landing page moves, reprint a label without guessing what it encoded, answer "who made this and when," and delete the code when the record goes away. Teams that skip it end up with a dashboard full of codes nobody can match to anything, which is the same as having none. Even for plain destinations from a URL code generator, one database column beats a folder of files named final_v3.

If nobody on the team writes code

No-code automation platforms cover most of this. A trigger fires on a new spreadsheet row, form response, or CRM record; an HTTP step calls the generator; a later step writes the result back. Real integrations run this way for years without an engineer touching them.

Two things to plan for. These platforms meter tasks, so a backfill can burn a month's quota in an afternoon; push large jobs through a bulk upload instead. And their error handling is quiet by default, so a step that fails at 2am may sit in a run log nobody opens. Add an explicit failure notification to a channel a human reads.

Start narrow. Pick the one record type that most needs a code, add a single column to that table for the identifier, and generate the first ten through the API by hand. Scan all ten with a real phone. If they resolve, wire up the trigger.

Share this article