Body
Markdown source. The chunker reads from here.
# Data source routing playbook (internal)
## Purpose
Tells the AI which system to query for which kind of customer question. Customers usually only know their email or their Shopify order name (e.g. "#321144"). They rarely know the CheckoutChamp order id, which is an 8-12 character hex string ("5074B2B25D"). The AI must translate between identifiers correctly before reaching for context.
## Identifier glossary
- **Customer email** — most reliable shared identifier. Always start here when available from the Zoho ticket header.
- **Shopify order name** — "#321144". The customer-facing storefront identifier. Lookup: Shopify Admin REST `/orders.json?name=#321144`.
- **CheckoutChamp order id (clientOrderId)** — "5074B2B25D". Internal order id. Lives in Shopify under `note_attributes[].clientOrderId`. Do not ask the customer for this.
- **CheckoutChamp customer id** — integer (e.g. 504653). Resolved by querying `/customer/query` first.
## Source-of-truth map
| Need | System |
|---|---|
| Customer profile, lifetime value, contact details | CheckoutChamp `customer/query` |
| Order details, items, fulfillment status, shipping address | CheckoutChamp `order/query` |
| Payment / refund / decline / chargeback details | CheckoutChamp `transactions/query` |
| Customer history (notes, billing events, fulfillment events) | CheckoutChamp `customer/history` |
| Customer-facing order receipt (storefront context) | Shopify Admin REST |
| Tracking, carrier, delivery status, checkpoints | Parcel Panel v2 |
| Internal policy / scripts / refund windows | KB / RAG (this system) |
## Default lookup path: email-first via CheckoutChamp
The Zoho ticket header almost always carries the customer's email. That's the cheapest, most reliable identifier we have, and it bypasses Shopify entirely for the common case. **Default behaviour is: email → CheckoutChamp directly.** Shopify is only needed when the customer pasted a Shopify order name and we want to disambiguate which order they meant.
For email-only lookups against CheckoutChamp, always use a **wide date range** (`startDate=01/01/2000`, `endDate=12/31/2099`). The upstream API requires both fields when querying by email and "all time" gives us everything we need.
## Routing by ticket intent
### Order status, delivery question, "where is my order"
1. CheckoutChamp `order/query` by email (wide date range) → pick the most recent order, unless the ticket clearly names an older one.
2. If the question is specifically about the package itself, then call Parcel Panel v2 with the Shopify order id or order name.
3. Apply the shipping language guardrail when summarising for the customer.
### Payment, refund, decline, charge, cancellation, billing question
1. CheckoutChamp `customer/query` by email → get `customerId`.
2. `order/query` and `transactions/query` (by customerId or orderId, no date range needed).
3. If no specific order is referenced, default to most recent unless the ticket clearly mentions an older one.
### Subscription / rebill question
1. `customer/history` filtered to TRIAL_*, REBILL_*, MEMBERSHIP_* category types.
2. `transactions/query` with `billType=RECURRING` for billing-cycle history.
### Tracking, shipment, package location
1. Parcel Panel v2 — by Shopify order name or order id, or by tracking number if the customer pasted one.
2. CheckoutChamp only if order identity needs cross-verification (rare).
3. Apply the shipping language guardrail (separate doc).
### Customer provides only email (most common case)
1. CheckoutChamp `customer/query` by email (wide date range).
2. CheckoutChamp `order/query` by email (wide date range) for recent orders.
3. `customer/history` by customerId for fuller context (filtered for system noise).
4. Skip Shopify and Parcel Panel unless the question requires storefront or shipping context.
### Customer provides Shopify order name (e.g. "#321144")
This is the disambiguation path. Use it when email gives multiple plausible orders, or when the customer's email isn't matching CheckoutChamp cleanly.
1. Shopify Admin REST `/orders.json?name=#321144`.
2. Read `note_attributes[].clientOrderId` from the response — this is the CheckoutChamp order id.
3. Query CheckoutChamp `order/query` by that orderId (no date range needed).
### Customer provides CheckoutChamp order id (rare)
1. CheckoutChamp `order/query` directly by orderId. No date range needed.
## Split / upsell order awareness
A single CheckoutChamp `clientOrderId` can map to multiple Shopify orders. This happens when an upsell exports late: Shopify already received the original order, so the upsell creates a second Shopify record but keeps the same `clientOrderId` in its `note_attributes`. When summarising the customer's purchase journey, treat all Shopify rows that share a `clientOrderId` as the same purchase.
## CheckoutChamp history noise filter
Customer history rows where `agentName` is `System` or `apiuser@nebroo.com` are webhook dispatches, custom-field flips, and other internal events. Useful for backend reasoning. **Never** quote these to a customer. The retrieval code already filters them out via `lib/integrations/checkoutchamp/history.ts`.
## Customer-facing redaction rules
Even when the AI uses backend data to reason, never expose:
- Internal agent names or apiuser identifiers
- Webhook profile names ("Meta CAPI v2", "Email Validation")
- Internal numeric ids (CheckoutChamp `actualOrderId`, Shopify internal id)
- Supplier or warehouse origin details
- Custom-field flips and source-value tracking ids
## When to ask the customer for more info
If the email has multiple plausible matches and no Shopify order name was provided, ask once: "Could you share the order number from your confirmation email (it usually starts with #)?" Do not guess.Metadata
Typeplaybook
Product line—
Languageen
Approved byakhlas@nebroo.com
Approved at2026-05-06 08:11
Freshness due2026-08-04 08:11
Created2026-05-06 08:11
Updated2026-05-06 08:11
Chunks
10 chunks · embedding pending (10)
- #0# Data source routing playbook (internal)
- #1## Purpose Tells the AI which system to query for which kind of customer question. Customers usually only know their email or their Shopify order name (e.g. "#321144"). They rarely know the CheckoutCh…
- #2## Identifier glossary - **Customer email** — most reliable shared identifier. Always start here when available from the Zoho ticket header. - **Shopify order name** — "#321144". The customer-facing s…
- #3## Source-of-truth map | Need | System | |---|---| | Customer profile, lifetime value, contact details | CheckoutChamp `customer/query` | | Order details, items, fulfillment status, shipping address |…
- #4## Default lookup path: email-first via CheckoutChamp The Zoho ticket header almost always carries the customer's email. That's the cheapest, most reliable identifier we have, and it bypasses Shopify …
- #5## Routing by ticket intent ### Order status, delivery question, "where is my order" 1. CheckoutChamp `order/query` by email (wide date range) → pick the most recent order, unless the ticket clearly n…
- #6## Split / upsell order awareness A single CheckoutChamp `clientOrderId` can map to multiple Shopify orders. This happens when an upsell exports late: Shopify already received the original order, so t…
- #7## CheckoutChamp history noise filter Customer history rows where `agentName` is `System` or `apiuser@nebroo.com` are webhook dispatches, custom-field flips, and other internal events. Useful for back…
- #8## Customer-facing redaction rules Even when the AI uses backend data to reason, never expose: - Internal agent names or apiuser identifiers - Webhook profile names ("Meta CAPI v2", "Email Validation"…
- #9## When to ask the customer for more info If the email has multiple plausible matches and no Shopify order name was provided, ask once: "Could you share the order number from your confirmation email (…