| name | generate-sample-transactions |
| description | Generate sample EDI transactions (850 POs, 856 ASNs, 810 invoices, 855 acks, 860 PO changes, 812 credit/debit adjustments) and inject them into Orderful as test-stream transactions, so a customer's connector and integration can be tested before their partnership is live. Uses real production transactions from comparable customers as the structural baseline and substitutes the target customer's product/SKU data. Triggers: 'generate sample 850s for [customer]', 'pre-stage test transactions for [customer] with [partner]', 'manufacture test PO for [customer]', 'inject sample [doc] for [customer]', 'create a test 850 from [partner] to [customer]'. Handles both phases — synthetic when product catalog is unknown (pre-NetSuite-access), real once the customer's catalog is pulled from their ERP. Always uses test stream, never live. Always uses real wire structure from existing partnerships. |
Generate Sample Transactions
What this skill does
For a target customer about to start trading with a partner, generate realistic sample EDI transactions and inject them into Orderful's test stream so the customer's connector / integration can be tested before their partnership is live. The samples are grounded in real production traffic from existing customers trading with the same partner — so the wire structure is accurate, not synthesized from a spec.
Two phases, depending on what's known:
- Phase 1 — Synthetic catalog. Customer hasn't granted ERP access yet, so we don't have their real product catalog. Use the handoff doc + public sources to manufacture realistic SKU codes / UPCs / pricing. Inject samples to give the connector something to ingest.
- Phase 2 — Refresh from real catalog. Once ERP access lands, pull the customer's actual product catalog and regenerate samples with real UPC / SKU / case-pack data. Re-inject; the test stream now matches what production will look like.
The skill always uses the test stream (never live) and never sends to a real partner — these are seeded transactions for connector validation only.
When this fires
Use whenever you need to put a transaction in front of a customer's connector before their partnership routes real traffic. Typical triggers:
- "Generate sample 850s for [customer]"
- "Pre-stage test transactions for [customer] with [partner]"
- "Manufacture a test PO for [customer]"
- "Inject sample [doc] for [customer]"
- "Create a test 850 from [partner] to [customer]"
- "Refresh [customer]'s test transactions with their real catalog"
Don't fire for:
- Live-stream test data the customer needs to send THROUGH the partnership (that's a real test transaction, after the partnership is up).
- Partners we don't have a comparable customer for — without a real reference, the wire structure is a guess.
Phase 1 — Synthetic catalog (pre-ERP-access)
Inputs to gather
-
Target customer — name, Orderful org ID, ediAccount ID, ISA ID, test ISA ID (often the same as prod for customers without a sandbox). Resolve via search_organizations or the onboarding profile.
-
Trading partner — partner name, partner Orderful org ID, partner test ISA ID. Resolve via the TP playbook + search_organizations. AOC profile (in Jira project AOC) typically has these.
-
Transaction types to generate — usually 850 is the starting point (PO from partner to customer). Other inbound docs (860, 812) and outbound responses (855, 856, 810) can be generated by the same skill for round-trip testing.
-
Customer product info — from the onboarding profile / handoff doc. Each product needs:
- Internal SKU code (used in PO1's VN qualifier — vendor item number)
- UPC-12 (used in PO1's UP qualifier — synthetic if no real GS1 assignment yet)
- UCC-14 case code (used in PO1's UK qualifier — synthetic, derived from UPC if no real assignment yet)
- Case pack count (used in itemPhysicalDetails)
- Product description (used in PID loop)
- Pricing (illustrative if no contracted pricing yet)
-
Partner-assigned vendor number — used in REF*IA segment of inbound docs. Often unknown pre-partnership — use a placeholder and flag for refresh.
Steps
-
Find a comparable customer. Look for an existing customer that's currently trading with this partner via the same channel. Examples:
- For KeHE-via-SPS new vendors → Olipop (org 72236) is a good comparable
- For Whole Foods → look at any DSD or specialty-natural CPG customer
- For Target via SPS → look at any general-merchandise CPG via SPS
Use search_organizations + get_account_context to find one with active partnerships against the target partner.
-
Pull recent real transactions from the comparable customer. Use the Admin API directly with the user's bearer token (the MCP tools enforce single-org context and won't work here):
curl -H "Authorization: Bearer $TOKEN" \
"https://api.orderful.com/v2/transactions?ownerId={comparable_customer_org_id}&partnerIsaIds={partner_isa}&direction=in&limit=5"
Pull 3–5 recent transactions of the target doc type. This gives you structural variation (different DCs, different line counts, different timing patterns).
-
Extract the real wire structure. Parse the message JSON. Note:
- Envelope: ISA version (e.g., 00501), separators (component, repetition)
- GS envelope: version-release identifier (e.g., 005010)
- All present segments (BEG, REF, PER, ITD, DTM, TD5, N9, N1, PO1, PID, CTT)
- N1 loop entries (ST/BT/VN/RI — which are present)
- REF qualifiers (VR/IA — what the partner uses)
- PO1 product qualifiers (UP/UK/IN/VN ordering)
- PID structure (description type code, characteristic codes)
- Hash totals and weight in CTT
- Any segments unique to the partner (N9 loops with terms text, etc.)
-
Cross-reference against the TP playbook + AOC profile. If the AOC profile says something different from production, surface the discrepancy and trust production. (We learned this with KeHE — AOC-230 said v4010, production was v005010. Production wins.)
-
Substitute the customer's product data into the payload.
- Replace UP / UK / IN / VN product identifiers with the target customer's values (placeholders if unknown)
- Replace pricing with placeholders if no contracted pricing
- Keep the partner-side identifiers REAL (DC addresses, GS1 prefixes, payment terms text, terms acceptance language, contact name conventions)
- Replace partner-assigned vendor number (REF*IA value) with a placeholder if not yet assigned
-
Build the payload. Construct a JSON document matching Orderful's POST /v2/transactions schema:
from: partner test ISA
to: customer ISA
type: {"name": "{TX_NAME}_PURCHASE_ORDER"} (or appropriate transaction type)
stream: "test" (NEVER live)
message: the full message structure
⚠️ Critical formatting gotcha: numeric fields in POST payloads must be strings, not numbers. Quantities, prices, hash totals, weights, line counts, pack counts, segment counts, ITD discount percent/days/net — all strings. The list endpoint returns them as numbers but POST rejects numbers.
-
POST to /v2/transactions using the admin bearer token:
curl -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d @payload.json "https://api.orderful.com/v2/transactions"
Expected response: HTTP 201 with {"id": <new_transaction_id>}.
-
Verify the transaction landed correctly. Pull it back via the list endpoint, confirm:
status: DISPATCHED
validationStatus: VALID
ruleErrors: [] (empty array)
source: APIV2 (correctly tagged as API-injected)
stream: test
- Line items round-trip correctly (all PO1 IDs preserved)
-
Document what's synthetic vs. real. Update the customer's onboarding profile (or a dedicated sample-transactions doc) with:
- Transaction IDs that were injected
- What fields are placeholders (vendor number, UPCs, SKU codes, prices)
- What needs to be substituted when real values land
- The comparable customer used as the structural baseline
Anti-patterns to avoid (Phase 1)
- Never expose another customer's actual UPC, SKU, pricing, vendor number, or buyer item codes in the synthetic output the target customer or their team sees. Use the structure, never the data.
- Never push to live stream by accident. Default and enforce
stream: "test".
- Never assume the AOC profile is right over production traffic. When they disagree, production wins. Surface the discrepancy via
sync-tp-network-profile.
- Don't generate samples for a doc type that the customer's partnership isn't scoped to send/receive. Only generate the docs that match the trade request's transaction set.
- Don't generate sub-hourly variation. Two or three samples (one happy-path single-line, one multi-line, optionally one edge case like a PO cancellation) is usually enough for connector validation. More is noise.
What sits in Orderful after Phase 1
The target customer's test stream has working sample transactions, validated and dispatched, ready for the customer's connector to pull (once routing is configured via partnership) or for direct fetch by ID.
The team has a documented inventory of which fields are real vs. placeholder.
Phase 2 — Refresh from real catalog (post-ERP-access)
Once the customer grants ERP access (typically NetSuite, sometimes SAP, Microsoft Dynamics, etc.), pull their real product catalog and regenerate the samples with accurate data.
Inputs to gather (Phase 2)
- ERP access confirmed — Orderful has been granted access to the customer's ERP system.
- Item master access — typically via the ERP connector (Mosaic API NetSuite Connector) or direct SOAP/REST API. Pull:
- All SKU codes for products in scope
- UPCs and case codes for each SKU
- Standard case pack counts
- Product descriptions
- Current contracted pricing (if available)
- Customer master entry for the trading partner — confirms the partner is set up in the ERP with the correct ship-to/bill-to addresses.
- Partner-assigned vendor number — should be in the customer master record by now if the partner has activated the vendor.
Steps
-
Pull the real catalog from the customer's ERP. For NetSuite Connector customers, use the Mosaic API endpoints to read item master records. Capture the canonical SKU code, UPC, UCC-14, case pack, description, and any retailer-specific pricing.
-
Regenerate the sample transactions with real values substituted for the Phase 1 placeholders. Keep the same structural pattern (since the partner's wire format hasn't changed) — only the product identifiers and pricing change.
-
Inject the refreshed samples as new test transactions. Optionally cancel/archive the Phase 1 placeholders to avoid confusion.
-
Update the documentation noting which transactions are now backed by real catalog data and which (if any) still have placeholders (e.g., partner-assigned vendor number still pending).
-
Notify the integration owner (the engineer wiring the connector) that the test stream now contains real-catalog samples — they may want to re-run any prior tests with the refreshed data.
Anti-patterns to avoid (Phase 2)
- Don't keep both Phase 1 and Phase 2 samples active in the test stream simultaneously unless you explicitly want to test the connector's resilience to data variation. Default: replace.
- Don't refresh without notifying. A connector engineer testing against the old samples will see surprising failures if the data changed mid-flight.
- Don't pull the customer's full catalog if only 3–5 SKUs are in scope. The samples are for connector validation, not exhaustive coverage. Use the SKUs the trading partner has actually accepted.
Reference: KeHE / Day Dream Nutrition (first real run, May 19 2026)
The skill was built from a real run on Day Dream Nutrition → KeHE. Notes from that run:
- Comparable customer: Olipop (org
72236, ISA DRINKOLIPOP). Pulled 5 recent KeHE 850s.
- Real wire structure surfaced: X12 v005010 (AOC-230 had said v4010 — corrected via
sync-tp-network-profile).
- Customer placeholder data: Day Dream's three SKUs (Morning Energy, Midday Boost, Nighttime Relaxation), 30ct case pack, synthetic UPCs (
850077012001 series), placeholder vendor number (02240756).
- Two samples injected: Sample 1 (single-line PO to KeHE Aurora CO DC, transaction ID
921777640), Sample 2 (3-line multi-SKU PO to KeHE Romeoville IL DC, transaction ID 921778959).
- Both validated:
DISPATCHED / VALID / zero rule errors.
- Refresh planned: once Kalyan grants NetSuite access, pull Day Dream's real catalog and regenerate. Until then, the synthetic samples are the test substrate.
See outputs/day-dream-kehe-sample-850s.md for the full annotated reference.
Final sanity check before injecting
- Did the comparable customer's transactions confirm the partner's wire structure? (If you couldn't find a comparable customer or only have stale data, surface that and don't proceed — synthesizing from a spec is a known failure mode.)
- Did I use
stream: "test" everywhere? (Never live.)
- Did I stringify all numeric fields in the POST payload?
- Did I scrub all of the comparable customer's actual product data (UPC, SKU, pricing, vendor number) from the output payload?
- Did I document what's synthetic vs. real so Phase 2 knows what to refresh?
- Did I verify the injected transaction has
validationStatus: VALID and ruleErrors: []?
If any of these is no, stop and fix before delivering.