P3 MEDIA
The Shopify agency for category-leading brands
SOLUTION BRIEF · CONFIDENTIAL
Spectrum Brands × P3 × Shopify
Prepared 06 / 08 / 2026
Inbound order architecture · To-be
Order ingest, rebuilt around the API.
The current design pushes every order to middleware over a synchronous webhook with a five-second response window — and times out, duplicating orders and forwarding fraud before payment clears. The redesign moves fraud and payment decisioning entirely into Shopify. Middleware pulls only orders tagged Shopify:Approved, so nothing unverified ever reaches SAP.
5s → 0
No webhook response window
100%
Fraud screened before ingest
2
Decoupled flows: tag, then pull
2026-04
Admin API, schema-validated
01
Risk tagging, inside Shopify
Risk is not known the instant an order is created — Shopify resolves it asynchronously, passing through a PENDING state. So tagging runs off the risk assessment, not off order creation. Shopify Flow reads riskLevel and writes exactly one of three tags.
Order created
orders/create
Risk assessed
order.risk → riskLevel
Shopify Flow branch
evaluates riskLevel
Risk = Medium / High
Tag for review
Shopify:Pending
Business user reviews
finance / CS team
Low auto-tag and a manual approval reach the same Shopify:Approved state
02
API-pull ingest, Shopify → SAP
This replaces the webhook push. The middleware polls the orders query filtered to the approved tag and paid status, dedupes on the Shopify global ID, accepts each order onto a JMS queue, and processes one-by-one into S/4HANA. Unapproved orders are never returned — so they are structurally impossible to import.
Shopify stores
Remington · Black & Decker · Emeril · Power XL
Approved orders
tag = Shopify:Approved
Other orders
Pending / Rejected
↳ not approved = never pulled,
never imported
Middleware pulls
orders query · filtered
Dedupe
on Shopify global ID
JMS queue
accept, then process
03
The verified API surface
Every operation below was checked against the Shopify Admin GraphQL schema, version 2026-04 — no hallucinated fields. Tap any node in the flows above to highlight the operation it maps to.
3 / 3 operations validated against Admin API 2026-04
01Read risk level
query · order.risk
query OrderRisk($orderId: ID!) {
order(id: $orderId) {
risk {
assessments {
riskLevel
provider { title }
}
recommendation
}
}
}
Enum riskLevel: LOW · MEDIUM · HIGH · NONE · PENDINGscope: read_orders
02Apply the tag
mutation · tagsAdd
mutation ApproveOrder($id: ID!) {
tagsAdd(
id: $id,
tags: ["Shopify:Approved"]
) {
node { id }
userErrors { field message }
}
}
tagsAdd officially supports the Order resource. Low auto-applies; Med/High → Pending → manual.resource: Order
03Pull approved only
query · orders (filtered)
query Approved($cursor: String) {
orders(
first: 50, after: $cursor,
query: "tag:Shopify:Approved
financial_status:paid"
) {
edges { node { id name tags } }
pageInfo { hasNextPage endCursor }
}
}
Dedupe on node.id (the Shopify global ID). Paginate via endCursor.scope: read_orders
04
One decision left for the room
The flows are settled. What remains is how Flow B is triggered — a tradeoff between latency and resilience that belongs to the architecture review, not to us to assume.
Open · trigger mechanism for Flow B
The diagram shows a middleware poll of the orders query, which matches the accept-and-queue preference raised in the working session. Two alternatives are worth weighing before the build locks.
Scheduled poll shown
Most resilient. No dependency on delivery guarantees; the queue absorbs spikes. Slight latency floor set by poll interval.
Webhook on order update
Lower latency, tag-filtered. But webhooks can self-disable on repeated failure — the original fragility.
Shopify Events
The newer webhook successor. Promising, still stabilizing — Shopify is sending the developer reference.