Advanced TRADE Quoteability Playbook
Status: Active
Version: v1
Last updated: 2026-04-16
This playbook documents the deployed advanced TRADE path for one-off classification review, approval, compliance quoteability, and landed-cost readiness. It is intentionally not a fourth canonical quickstart. Use it when you already understand the base auth flow and need the reviewable single-item path rather than the TRADE feed workflow.
Companion docs:
- Public API contract pack:
docs/api/public-api-contract-v1.md - OpenAPI contract (current):
docs/api/openapi/rgl8r-public-api-v1.3.0.yaml - Landed cost route contract:
docs/api/landed-cost-contract-v1.md - Agent integration kit:
docs/api/agent-integration-kit-v1.md
What this path covers
This advanced path is for callers who need to:
- classify a single item,
- route that result into the review surface,
- approve it through the existing one-off apply seam,
- evaluate compliance quote readiness for a specific corridor, and
- confirm that landed-cost authority is also available.
The runtime contract is modular by design:
POST /api/trade/classifyandPOST /api/trade/classify/batchremain intelligence routes.POST /api/trade/classify/reviews*is the review surface.POST /api/trade/classify/applyremains the single public one-off persistence seam.POST /api/compliance/checkreturns policy/document readiness only.POST /api/trade/landed-costseparately determines whether authoritative landed-cost data is available.
The classify -> review boundary
The production hardening fix in this pass is narrow and explicit.
Before the fix, callers could hit review-create validation errors because classify emitted nullable optional strings such as hs10Code: null, while review create accepted optional strings but not null for those fields.
After the fix, the published handoff contract is:
- take a review-eligible classify result from
POST /api/trade/classify, - add the approval identity fields,
- if
classification.needsReview !== true, also setforceReview: true, - send it directly to
POST /api/trade/classify/reviewswith no client-side artifact cleanup.
The server now normalizes the classification artifact boundary consistently for classify responses, review create ingress, and review detail/list/patch serialization.
Canonical artifact rules
Top-level optional strings are normalized from string | null | undefined to string | undefined:
hsCodehs6Codehs10CodedescriptionreferenceDescriptioncategoryreasoningsourcemodelprovidedCodeState
Normalization rules:
- trim strings,
- omit when
null,undefined, or empty after trim, - preserve non-empty strings unchanged.
Other artifact rules:
- preserve
needsReview: falseexactly, - preserve
confidence: 0andlatencyMs: 0exactly, - preserve arrays exactly, including empty arrays,
- preserve unknown passthrough fields when non-nullish,
- omit unknown passthrough fields only when
nullorundefined.
latencyMs, if present, is classify-time telemetry provenance only. It reflects the original classify call, not review-create timing.
Review eligibility gate
This pass does not broaden review eligibility.
Review creation remains gated exactly as deployed:
- direct create is allowed when
classificationArtifact.needsReview === true - otherwise the caller must send
forceReview: true
Use the term review-eligible classify result in implementation and support language. If a classify result is not review-eligible by default, the caller can still route it into the review surface by explicitly setting forceReview: true.
Approval identity requirements
Review creation requires approval-ready identity up front:
- required:
sku - required:
originCountry - optional:
destinationCountry
Implications:
sku + originCountryis enough for approval-capable one-off persistence through the existing apply seam.- If
destinationCountryis also supplied, the approved result may additionally materialize corridor-scoped trade profile state. - If the original classify call omitted
skuororiginCountry, the classify result may remain intelligence-only, but it cannot be entered into the review queue until the caller supplies those fields at review creation.
End-to-end sequence
1. Classify
CLASSIFY=$(curl -sS -X POST "$BASE_URL/api/trade/classify" \
-H "Authorization: Bearer $RGL8R_BEARER_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"description": "Cotton knit shirt for adults",
"originCountry": "CN",
"destinationCountry": "US"
}')The response body contains classification.
2. Create a one-off review from the raw classify artifact
If the classify result is already review-eligible (needsReview === true), you can create directly. If it is not, add forceReview: true.
REVIEW_CREATE=$(python3 - <<'PY'
import json, os
classification = json.loads(os.environ['CLASSIFY'])['classification']
payload = {
'sku': 'ADV-TRADE-DEMO-001',
'originCountry': 'CN',
'destinationCountry': 'US',
'productDescription': 'Cotton knit shirt for adults',
'classificationArtifact': classification,
}
if classification.get('needsReview') is not True:
payload['forceReview'] = True
print(json.dumps(payload))
PY
)
REVIEW=$(curl -sS -X POST "$BASE_URL/api/trade/classify/reviews" \
-H "Authorization: Bearer $RGL8R_BEARER_TOKEN" \
-H "Content-Type: application/json" \
-d "$REVIEW_CREATE")3. Patch the review if needed
Wave 1 patchable fields are intentionally narrow:
classificationArtifactchosenHsCode
Nothing else is patchable.
REVIEW_ID=$(echo "$REVIEW" | python3 -c "import sys,json;print(json.load(sys.stdin)['review']['id'])")
REVISION=$(echo "$REVIEW" | python3 -c "import sys,json;print(json.load(sys.stdin)['review']['revision'])")
PATCHED=$(curl -sS -X PATCH "$BASE_URL/api/trade/classify/reviews/$REVIEW_ID" \
-H "Authorization: Bearer $RGL8R_BEARER_TOKEN" \
-H "Content-Type: application/json" \
-d '{"chosenHsCode":"99038512"}')4. Approve
Approval uses optimistic locking via revision.
PATCHED_REVISION=$(echo "$PATCHED" | python3 -c "import sys,json;print(json.load(sys.stdin)['review']['revision'])")
APPROVED=$(curl -sS -X POST "$BASE_URL/api/trade/classify/reviews/$REVIEW_ID/approve" \
-H "Authorization: Bearer $RGL8R_BEARER_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"revision\":\"$PATCHED_REVISION\"}")Under the hood, approval still flows through the existing one-off apply seam. There is no second persistence implementation.
5. Check compliance quote readiness
COMPLIANCE=$(curl -sS -X POST "$BASE_URL/api/compliance/check" \
-H "Authorization: Bearer $RGL8R_BEARER_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"hsCode": "99038512",
"originCountry": "CN",
"destinationCountry": "US",
"entityType": "SKU",
"entityId": "ADV-TRADE-DEMO-001"
}')Configured-mode response fields of interest:
policyModequoteReadinessblockingReasonsmissingRequiredDocuments
quoteReadiness means policy/document readiness only:
quoteableblockedrequires_documentsunconfigured
In legacy mode, the response stays shape-stable with:
quoteReadiness = nullblockingReasons = []missingRequiredDocuments = []
6. Check landed cost separately
LANDED_COST=$(curl -sS -X POST "$BASE_URL/api/trade/landed-cost" \
-H "Authorization: Bearer $RGL8R_BEARER_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"productValue": 100,
"hsCode": "99038512",
"originCountry": "CN",
"destinationCountry": "US"
}')Full quoteability in Wave 1 requires both halves to pass:
/api/compliance/checkreturnsquoteReadiness = "quoteable"/api/trade/landed-costreturnsstatus = "authoritative"
A compliance response can be quoteable while landed cost is still unavailable. That is valid Wave 1 behavior because policy/document readiness and landed-cost authority are separate gates.
Configured-mode corridor behavior
Advanced quoteability is corridor-aware.
Policy modes:
legacy: tenant has zero corridor rowsconfigured: tenant has one or more corridor rows
Configured-mode matching order:
- exact
(originCountry, destinationCountry)match - wildcard-origin
(*, destinationCountry)match - otherwise no match
There is no destination-only match.
unconfigured_corridor meaning
When a tenant is in configured mode and landed cost has no enabled exact-or-wildcard corridor match, POST /api/trade/landed-cost returns a route-level business outcome:
{
"authority": "internal",
"status": "unconfigured_corridor",
"breakdown": null,
"reason": "no_enabled_matching_corridor",
"metadata": {
"policyMode": "configured",
"originCountry": "CN",
"destinationCountry": "US",
"corridorConfigured": false
}
}This is not an engine-level landed-cost status. It is a route-layer precheck that says configured quote mode exists for the tenant, but the requested corridor has not been enabled.
On the compliance side, the corresponding configured-mode miss is:
quoteReadiness = "unconfigured"
The obligations payload still returns normally. Only the readiness summary reflects configuration debt.
What this playbook does not change
This pass does not:
- turn advanced TRADE into a fourth canonical quickstart,
- add a new public approval route,
- broaden review eligibility beyond
needsReview/forceReview, - change the engine-level landed-cost union,
- redefine compliance readiness as full quoteability.
It hardens the existing deployed runtime and documents the additive advanced TRADE surface that already exists.