How to Validate and Standardise Shipping Addresses with AI Before Shipping
Use an AI step to catch incomplete or inconsistent shipping addresses on WooCommerce orders, standardise them into a clean format, and put risky orders on hold before they ship.
What This Integration Does
AI address validation reads an address the way an experienced dispatcher would: it notices that a postcode does not belong to the suburb, that "Unit" is missing from an apartment block address, that the state is written three different ways, or that the customer typed their phone number into the street line. In Spojit you do this with a Connector node in Agent Mode and a Response Schema, so the model returns a fixed, machine-readable verdict for every order rather than free text. The workflow then standardises the address, puts doubtful orders on hold, and leaves a private note explaining why.
An AI check is different from a postal database lookup. A model can tell that an address is malformed or internally inconsistent, but it cannot prove a building exists. Use this workflow when you have no address API, when you ship to countries an address API covers poorly, or as a cheap first pass before a paid lookup such as the Google Address Validation API. The workflow runs on a schedule, checks orders that arrived since the last run, and only writes notes and statuses, so re-running it is safe.
Prerequisites
- A WooCommerce connection with a REST API key that has read and write access.
- Enough AI credits on your plan for one short agent call per order. A small, fast model is plenty for this task.
- A short written policy for your store: which countries you ship to and what you consider "hold" versus "ship".
Step 1: Schedule Trigger
Add a Trigger node with type Schedule and the cron */10 * * * * in your store's timezone. Ten minutes is fast enough that the warehouse has not started picking.
Step 2: Fetch New Processing Orders
Add a Connector node on WooCommerce in Direct Mode with list-orders. Set status to processing, per_page to 100, and after to the trigger time minus 15 minutes in ISO 8601 (use the Date & Time connector's subtract and format tools). Name the output orders. Run the step once and check the output panel for the exact path to the order list.
Step 3: Loop and Ask the AI for a Verdict
Add a Loop in ForEach mode over the orders, with the item variable order and On iteration error set to Continue with the next item. Inside it, add a Connector node in Agent Mode. Agent Mode needs a connector; pick Text Tools. Its tools only reshape text, so the step cannot change anything in your store (an empty tool selection would give the agent every tool on the connector, which is why a write-capable connector is the wrong choice here). Prompt:
You check shipping addresses for an online store that ships to Australia and New Zealand.
Address:
{{ order.shipping.address_1 }}
{{ order.shipping.address_2 }}
{{ order.shipping.city }} {{ order.shipping.state }} {{ order.shipping.postcode }}
{{ order.shipping.country }}
Decide whether a courier could deliver this as written.
Return "ship" if it is complete and consistent, "hold" if a courier would likely fail,
and "review" if you are unsure. Standardise the address: correct capitalisation,
expand obvious abbreviations, put unit numbers in address_1 as "Unit 4, 12 Smith Street".
Never invent a street number, unit number or postcode that is not in the input.
Add a Response Schema so the answer is always structured:
{
"type": "object",
"properties": {
"decision": { "type": "string", "enum": ["ship", "hold", "review"] },
"problems": { "type": "array", "items": { "type": "string" } },
"address_1": { "type": "string" },
"address_2": { "type": "string" },
"city": { "type": "string" },
"state": { "type": "string" },
"postcode": { "type": "string" }
},
"required": ["decision", "problems"]
}
Name the output check.
Step 4: Hold Doubtful Orders
Add a Condition node that passes when {{ check.decision }} is not ship. On that branch:
- A WooCommerce step with
update-order:id{{ order.id }},statuson-hold. - A WooCommerce step with
raw-api-request:methodPOST,path/orders/{{ order.id }}/notes,body:{ "note": "Address check ({{ check.decision }}): {{ check.problems }}. Suggested: {{ check.address_1 }}, {{ check.city }} {{ check.state }} {{ check.postcode }}", "customer_note": false }
The note is private, so the customer does not see it, and the on-hold status keeps the order out of the pick list.
Step 5: Standardise Clean Addresses
On the ship branch, you can write the standardised address back so labels print neatly. Use raw-api-request with method PUT, path /orders/{{ order.id }} and a body of { "shipping": { "address_1": "{{ check.address_1 }}", "address_2": "{{ check.address_2 }}", "city": "{{ check.city }}", "state": "{{ check.state }}", "postcode": "{{ check.postcode }}" } }. Only do this once you have reviewed a week of verdicts and trust them.
Tips
- Put your rules in the prompt: PO box policies, rural delivery, islands you do not ship to and courier-specific formats all belong in the prompt. The model applies them consistently on every order.
- Use review for people, hold for blockers: send
reviewverdicts to Slack for a quick human look instead of holding them, so true problems stay rare and visible. - Combine with an address API: run this AI check first and call a paid lookup only for
reviewverdicts. You pay for the lookup on a small share of orders. - Keep a sample: log each verdict to a sheet or database for the first few weeks so you can see how often the model and the courier agree.
Common Pitfalls
- Letting the model invent data: without the "never invent" line, a model may fill in a plausible postcode. Keep that rule in the prompt and never auto-correct a held order.
- Overwriting customer addresses too early: writing the standardised address back changes what the customer typed. Start with notes only.
- Skipping the schema: without a Response Schema the answer is free text and the Condition cannot route it reliably.
- Orders without shipping: virtual products have an empty
shippingblock. Skip them with a Condition before the agent step so you do not spend credits on them.
Testing
Create three test orders: a complete address, one with the postcode from a different state, and one missing a unit number for an apartment building. Run the workflow manually and read each check output in the run history. Adjust the prompt until all three land on the right branch, then turn the schedule on.