How a registration gets submitted
Before anything is verified or stored, the system has to receive the registration safely: a scan or a short form, one public endpoint, and enough checking that a stranger can’t flood it or register a serial they never bought. This post is about that front door — how a QR scan or a form submission becomes a single, claimed job ready to verify.
Key takeaways
- Registration starts with a QR sticker on the product or a short web form — both post to one Lambda Function URL, with no API Gateway.
- The form asks for two things only: the serial number and a proof of purchase; the QR pre-fills the serial so most buyers just add the receipt.
- The post is signed and rate-limited before anything runs, so a stranger can’t script thousands of fake registrations against the endpoint.
- A repeat submission of the same serial in a short window collapses to one job, so a double-tap or a flaky connection doesn’t create two.
- Nothing is verified or stored here — this step just turns a scan or a form into one clean, claimed job for the verifier to check.
From a scan to a job
Everything starts with the buyer doing the one thing warranty cards never manage to make them do: actually registering. The trick is to ask at the right moment and to ask for almost nothing. The moment is the unboxing, when the product is in their hands and the receipt is still in the bag; the “almost nothing” is a QR sticker on the product itself that opens a form with the serial already filled in. All the buyer adds is a proof of purchase — an order number, or a snap of the receipt — and taps send. Someone who’s lost the sticker, or bought second-hand, can reach the same short form and type the serial by hand.
That form posts to a single Lambda Function URL. There’s no API Gateway in front of it; a Function URL is a plain HTTPS endpoint on the function itself, which is all a form submission needs and the cheapest way to receive one. The function’s job here is not to decide whether the warranty is valid — that’s Part 3’s work, against the order records. Its job is narrower and it matters just as much: accept the submission safely, make sure it’s genuine and not a flood, and turn it into exactly one clean job. Most of this post is about that front door, because a public endpoint that anyone can post to is where a registration system either stays trustworthy or fills up with rubbish.
Two ways in, one door
The QR path and the typed path produce the same thing. Take Halewood Tools, a small brand selling cordless drills: every drill leaves the factory with a serial laser-etched on the battery foot and a QR sticker beside it. A tradesperson scans it on a wet Tuesday, the form opens showing HAL-DR18-004417, they paste the merchant’s order number, and send. A different customer bought the same drill as a gift, has no sticker to scan, so they open register.halewoodtools.co.uk, read the serial off the battery, and type it in. Both submissions land on the same Function URL carrying the same two facts — a serial and a proof of purchase — plus a little context the form adds automatically: which product line, and a timestamp. From here on, the system doesn’t care which way the buyer came in.
Keeping the form to two fields is a deliberate choice. Every extra box — name, address, email, model, date — is a reason to abandon the registration, and most of it the system can derive anyway: the order records already know who bought it, when, and what. Ask for the serial and the proof; recover the rest from the sale. The one contact detail the system does need for confirmations and reminders comes from the order record too, so the buyer never re-types what the business already holds.
Prove it’s genuine, then prove it’s new
A public URL invites abuse, so two checks run before the submission becomes a job. The first is authenticity and rate. The form is served with a short-lived signed token, and the post carries a signature the function verifies against a secret held in Secrets Manager; a request with no valid token is dropped with a 401. On top of that the endpoint is rate-limited per source, so nobody can script tens of thousands of guesses at serial numbers to see which ones register. Without this, a public registration form is an open invitation to pollute the warranty database; with it, only real submissions from the real form get through.
The second check is duplication. Buyers double-tap, connections drop and retry, and an over-eager scanner can fire the same form twice. The system must create exactly one registration job per serial, so the function writes a short-lived submission marker keyed on the serial using a conditional write to DynamoDB. The first submission in that window wins and creates the job; any repeat inside the window sees the existing marker and stops. This is only the submission guard — the permanent “one warranty per serial” rule is enforced later, at the store step in Part 4, with its own conditional write — but catching duplicates this early keeps the verifier from doing the same work twice.
Cleaning up before handing off
Before the job goes on the queue, the function does the small, unglamorous work that makes Part 3’s matching reliable. Serials arrive in a dozen shapes — with spaces, dashes, lowercase, a scanned barcode’s leading zeros — so the function normalises to one canonical form, the same form the order records use, so that hal dr18 004417 and HAL-DR18-004417 are the same unit. It reads the product line from the form (the QR encodes it; the typed form has a small dropdown) so the verifier knows which warranty terms apply. And it keeps the proof of purchase as given — an order number to match, or a receipt image to hand to a person if the automatic match can’t be made.
What it deliberately does not do is look anything up, compute anything, or send anything. No order records are read here, no expiry is worked out, no confirmation goes out. Keeping the public-facing function thin is what keeps it fast and cheap and hard to abuse: it does just enough to be sure the submission is real, singular, and tidy, then drops a clean job on the SQS queue — serial, proof, product line, timestamp — and returns. Part 3 picks it up and does the one thing that actually decides whether a warranty exists: checking it against a real sale.
Design rules that shaped the submission step
- One public surface. A single Lambda Function URL receives both the QR post and the typed form; there is no API Gateway and no other way in.
- Ask for two things. Serial and proof of purchase — everything else about the buyer is recovered from the order record, not re-typed.
- Verify before you trust. A signed token and a rate limit keep a public URL from being scripted into a pile of fake registrations.
- One submission, one job. A conditional write over a short window collapses double-taps and retries so the verifier never runs twice.
- Normalise at the door. The serial is cleaned to the canonical form the order records use, so matching later is a plain lookup.
- Decide nothing here. This step verifies no purchase and stores no warranty; it just hands a clean, singular job to Part 3.