3. Reviewing and approving codes
The Products screen
Products is the working queue. Each row shows:
| Column | What it is |
|---|---|
| Product | Title, vendor, product type |
| HTS code | The full ten-digit code, dotted for readability |
| Confidence | How well the product data supported the code |
| Status | Auto-classified / Suggested / Needs review / Approved / Overridden |
| Rationale | Why this code, in one line |
| Origin | Country of origin, if known |
| Base duty | The general (MFN) rate for that code |
Two tabs sit at the top. All products is everything; Needs attention filters to the rows actually waiting on you. Start there — on a healthy catalogue it is a short list.
You can search by title and add filters to narrow further.
A sensible review order
- Needs review first. These are the ones where the app is telling you it is not confident. They are also usually the ones where a two-word description fix would have produced a clean answer.
- Then Suggested. Skim the rationale. If it names the deciding factor and that factor is true of your product, approve it.
- Spot-check Auto-classified. You do not need to read all of them, but check a handful per category the first time — especially anything where your catalogue uses unusual materials.
Approving
Approving accepts the code and writes it back to Shopify, onto the product's HS code field (Product → Shipping → Customs information). That is the field Shopify itself uses for customs paperwork and duty calculation at checkout, so approving is what actually makes the code do something.
The code is written to every inventory item on the product, so multi-variant products all receive it.
Every code is re-checked at the moment it is written. Approval is not the last check — immediately before the write, DutyLookout confirms the code still exists in the tariff revision that is currently published, re-reads your auto-approve setting rather than trusting the one that was in force when the job was queued, and confirms that nothing you decided yourself has landed on the product in the meantime. If any of those fails, the write is refused and recorded as skipped: nothing reaches Shopify and the row stays in the app for you. In practice this is what stops a code approved shortly before a schedule revision from being written to your store after the line it names has been retired.
The check is made against the revision that is published now, not against any revision that was ever published. DutyLookout keeps every schedule revision it has downloaded — the ones it rejected as incomplete or malformed, and also last quarter's, which is perfectly good history but is no longer the schedule you are declaring under. A line that existed then and has since been retired does not count as existing. If there is no published revision at all, the write is refused rather than made on faith.
Nothing is ever written over a code you entered or overrode. That holds at the write itself, not just at classification time — if your own decision is the product's current one, the write is refused regardless of what produced the suggestion trying to land.
Country of origin is not written back. The origin you set in DutyLookout is used for duty estimates and stays in DutyLookout. Shopify's own Country/Region of origin field is left alone — the app does not put a customs declaration on your products that you did not enter there yourself. If you want it on the Shopify record too, set it in Shopify.
An approved code is not frozen. If you later edit the product so substantially that the classification no longer holds, DutyLookout re-classifies it and asks again.
Overriding
If you disagree, set your own code. An override is recorded as Overridden, kept in the audit trail with your value, and treated as authoritative — the app will not argue with you or quietly replace it later.
Override rather than ignore. A wrong code left in Needs review stays in the queue forever; an override closes it and teaches the audit trail what you actually declare.
Auto-approve
Settings has an auto-approve option. With it on, anything scoring 0.90+ is written back without waiting for you.
Worth turning on when you have reviewed enough of your catalogue to trust the 0.90+ band for the kinds of products you sell. Worth leaving off if you are in a regulated category, if your margins make a duty error expensive, or if you simply want a human on every code. It is off by default, deliberately.
Auto-approve never touches Suggested or Needs review rows.
Auto-approve waits for the second pass. Large imports — from about a hundred products at a time — are classified in a background batch, and on that path the line-selection pass is queued rather than run alongside the first one. So for a minute or two a product can hold a first-pass code that nothing has yet checked against the real statistical lines under its subheading. Auto-approve holds those rows back until the second pass has been over them; usually that is a single one-minute cycle, and then the verified code is written. A code the second pass cannot confirm is never written to Shopify automatically — it waits in the app for you, and approving it yourself is what sends it.
The audit trail
Export CSV produces the full decision history: every code, who or what decided it, the confidence, the rationale, and when. Each row records whether it came from the cache, the model, your approval, or your override.
Keep these. If a customs broker or an auditor asks why a product was declared under a particular code, this file is the answer, and it was written at the time rather than reconstructed afterwards.
Next: Duty estimates →