Part 5 of 7 · Photo tagger series ~5 min read

How a listing gets approved

A clean draft lands in the owner’s review queue at 2:01pm: the photo of the navy mug, with a title, alt text, tags, a category, and a short description, each one ready to read. There are three buttons. What happens when the owner taps one? That’s the whole point of the system — the tagger drafts, the human decides. This post walks through the three things the owner can do — approve, edit, reject — and how the store, the draft state, and the audit trail all stay in sync.

Key takeaways

  • Three actions per draft: approve (write to the store), edit (fix, then approve), reject (flag it).
  • Approve writes the listing fields to your store, or to an export sheet you import later.
  • Edit opens a form pre-filled with the draft — change a word, then approve.
  • Reject moves the photo to a flagged folder with a reason; nothing goes live.
  • Every action is logged with who did it, when, and the before-and-after — so it’s reversible.

Three actions on a draft

Three actions on a draft card A diagram showing one input on the left flowing into a draft review card, then branching into three action paths, all converging on an audit trail. Far left: a "Draft card" box showing the review card — the photo plus the drafted title, alt text, tags, category, and description — with three button placeholders below: Approve, Edit, Reject. The owner taps one button. The middle column shows the three branches. Branch one, Approve: a Function URL Lambda writes the listing fields to the store via its API, or appends a row to an export sheet for shops that import in bulk, then archives the draft and marks the photo done. Branch two, Edit: opens a form pre-filled with the drafted fields; the owner changes whatever is wrong — a colour word, a tag — and saves, which runs the same write-to-store step as Approve but records that a human edited the draft first. Branch three, Reject: moves the photo to the flagged folder in S3 with a reason the owner picks (wrong item, bad photo, will retake); nothing is written to the store. The right side shows the convergence: every action writes a row to the pt-audit DynamoDB table with timestamp, photo id, action, by-user, and a before-and-after snapshot of the fields. A note at the bottom: the tagger drafts and the human decides — approve is the only path to the store, and it is always a person's choice. Draft card photo + five fields [Approve] [Edit] [Reject] Action 1 Approve • Function URL writes the fields to the store • or an export sheet row • Draft archived, done Action 2 Edit • Form pre-filled with the drafted fields • Fix a word, then save → same write-to-store Action 3 Reject • Move photo to the flagged folder • Reason recorded — nothing goes live Audit trail DynamoDB pt-audit timestamp · photo_id action · by-user before / after The tagger drafts and the human decides — approve is the only path to the store.
Fig 5. Three actions per draft, three different effects. Approve writes the fields to the store. Edit lets the owner fix a word, then writes. Reject flags the photo and writes nothing. Every action writes to the audit trail.

Action 1: approve (the most common)

The draft looks right. The owner taps Approve. The button submits to a Function URL Lambda — a small web endpoint that runs the approve step without any heavy web server behind it. Two things happen. First, the listing fields are written where they belong: directly to the store through its API for shops that have one connected, or appended as a row to an export sheet for shops that prefer to import a batch by hand. Which path you use is a setting; the rest is identical. Second, the draft is archived, the photo is marked done, and an action: approved row is written to the audit trail with the owner’s name, the timestamp, and the exact fields that went out.

From the owner’s side this is one tap. The photo of the navy mug is now a real listing with a clean title, proper alt text, sensible tags, the right category, and a readable description — and it took ten seconds instead of three minutes.

Action 2: edit (fix one word, then approve)

The draft is close but not quite. The model wrote “navy,” but the product’s actual name is “midnight.” The owner taps Edit. A form opens, pre-filled with all five drafted fields, so the owner isn’t starting from scratch — they’re fixing one word in an otherwise finished draft. They change “navy” to “midnight,” leave everything else, and save.

Saving runs the exact same write-to-store step as Approve, with one difference recorded in the audit row: the action is edited, and the before-and-after snapshot shows what the owner changed. That snapshot is quietly useful over time — if the model keeps writing “navy” where the shop says “midnight,” the pattern shows up in the edits, and that’s a hint to add the preferred word to the style doc so future drafts get it right on their own.

Action 3: reject (this one’s wrong)

Sometimes the draft is fine but the photo isn’t the one that should be listed — it’s a duplicate, a bad angle, or an item that’s being discontinued. The owner taps Reject and picks a reason from a short list (wrong item, bad photo, will retake, discontinued). The photo is moved to the flagged folder in S3, the same place the automatic flags from Part 4 land, and nothing is written to the store. An action: rejected row records the reason and who rejected it.

Reject is deliberately a clean dead end, not a deletion. The photo and its draft stay in the flagged folder, so if someone rejected the wrong card by mistake, it can be found and re-queued. Nothing is ever truly thrown away — it’s moved, with a reason, where a person can find it again.

Every action is logged, every action is reversible

The pt-audit table records every approve, edit, and reject with the user who acted, the timestamp, and a snapshot of the fields before and after. If a listing went out with a typo, or the wrong photo got approved, a rep can run an “undo last action” through a small admin command that reads the previous-state snapshot and restores it — pulling the listing back or re-queuing the draft. The undo is itself an audit row, so the trail of who-changed-what stays clean.

This matters most when more than one person reviews. A small shop might have two people clearing the queue on a busy launch day. The audit trail is the shared memory: who approved which listing, what the model originally drafted, and what a human changed before it went live. When a customer later asks why a listing says what it says, the answer is one lookup away.

Next post: the cost breakdown. The whole pipeline above runs in coffee-money territory at SMB volume; Part 6 explains exactly where the dollars go and why the one vision call per photo is the only line that really moves.

All posts