SRS: Stage 3 KYC & Live Onboarding — UC_5.7: Flow 3G Market Data Payment
| Field | Value |
|---|---|
| BA in Charge | linh.nguyen34 |
| Date Created | 2026-08-08 |
| Version | v1.6 |
| Document References | Zapier Integration V7.pdf (Flow 3G lines 1251–1264; Flow 22 lines 2177–2215; Email Table D1 lines 730–732; Users table schema lines 339–352) · RFQ_ Stack Trading Prop Tech V7.pdf (Process Payment Webhook endpoint lines 1335–1373; Toggle Market Data endpoint lines 1218–1222; Generate Data Invoices endpoint lines 1575–1595; Get Market Data Status endpoint lines 1493–1498; Calculate Data Refund endpoint lines 1985–2000; customer_vault_id lines 1592–1595) · RFQ_ Website and Dashboard Implementation V7.pdf (Market Data Management UI lines 596–635; Market Data Lifecycle Disclosure lines 342–350; Step 7 Processing lines 506–512) |
UC Index
| UC_ID | Use Case Name | Business Description |
|---|---|---|
| UC_5.7 | Flow 3G — Market Data Payment | Handles the payment confirmation webhook from the payment processor after a Futures trader selects Option B (premium add-on feeds) in Flow 3F. On payment success: backend sets market_data_paid_until, pushes NEW_PAYMENT_SUCCESS event; Zapier Flow 3G sets setup_status = 'Complete', market_data_billable = True, evaluates the dual aggregation gate for Flow 3H. On recurring monthly billing failure (Flow 22 failure path): deactivates add-on feeds (NYMEX/CBOT/COMEX) via Rithmic API, keeps base CME feed active (firm-paid), sets market_data_billable = False, notifies the trader. |
Changelog
| Date | Version | Updated item | Before | After | Notes |
|---|---|---|---|---|---|
| 2026-08-08 | v1 | Initial creation | — | Created SRS for UC_5.7 (Flow 3G) | First authoring pass |
| 2026-08-08 | v1.1 | Cross-check vs RFQ_ Stack Trading Prop Tech V7.pdf | Multiple gaps and inaccuracies | (1) Added backend Process Payment Webhook intermediary step between payment processor and Zapier; (2) Added market_data_paid_until field set by backend on MARKET_DATA payment; (3) Corrected Reactivate button to use POST /toggle-market-data (not POST /execute-checkout); (4) Added Inactive_Hold status for feed-paused traders; (5) Added GET /market-data-status endpoint and market_data_flags JSON field; (6) Added Calculate Data Refund endpoint to BR_5.7.7 Level 3 flow; (7) Clarified market_data_flags (JSON) vs market_data_billable (Zapier operational field) | Source: RFQ_ Stack Trading Prop Tech V7.pdf §Process Payment Webhook, §Get Market Data Status, §Calculate Data Refund, §Toggle Market Data |
| 2026-08-10 | v1.2 | Q12: Tiered billing formula resolved — conflict flag removed; BR_5.7.9 updated with confirmed authoritative formula | ⚠️ Source conflict flag (Zapier V7 summary vs RFQ V7 tiered spec) | Formula confirmed: Level 1 & 2 = Total_Market_Data_Cost; Level 3+ = Total − Base_CME_Data_Cost | QnA STAGE3-013 confirmed 2026-08-10 |
| 2026-08-11 | v1.3 | Q4: Last_Data_Payment_Status reset confirmed — atomic reset at reactivation payment is mandatory; BR_5.7.13 added; §4, §5 Step 2c, §6 Reactivate Alt Flow updated | Last_Data_Payment_Status reset timing undefined | Reset MUST occur atomically alongside Market_Data_Billable = True and market_data_paid_until at reactivation payment — deferring to next billing cycle causes State-Machine Lockout double-deactivation bug | QnA STAGE3-031 confirmed 2026-08-11 |
| 2026-08-11 | v1.4 | Q13: T365/CR-20260730-001 flagged as [UNVERIFIED IN V7]; BR_5.7.11 reframed as universal gateway mandate; BR_5.7.12 updated to include correlation_id | T365 treated as NMI equivalent (unverified assumption) | T365 not documented in V7 specs; mandate reframed: ALL gateways must pass user_id/product_id/addon_ids in metadata; all gateways must support HMAC/JWS + IP allowlisting + provider_event_id + correlation_id | QnA STAGE3-032 confirmed 2026-08-11 |
| 2026-08-12 | v1.6 | §5 Sub-flow A Step 2: market_data_flags write added to atomic transaction; BR_5.7.8 updated — market_data_flags written by Node.js middleware only (not Zapier); webhook security BR_5.7.12 cross-reference added to §8 | market_data_flags writer undocumented (Q1 open); BR_5.7.8 listed writer as "Backend / Zapier" | Confirmed (STAGE3-047): Node.js middleware writes market_data_flags JSON column atomically with setup_status = 'Complete' and market_data_billable = True at Process Payment Webhook. Zapier does NOT write this field. BR_5.7.12 already present — security mandate note added to BR_5.7.8. | STAGE3-047 confirmed 2026-08-12; Q8/STAGE3-016 confirmed 2026-08-10 |
| 2026-08-16 | v1.7 | §3 Pre-conditions Sub-flow A | "payment link was emailed to trader" / "Trader completed checkout on payment processor's hosted page" | Payment completed on Stack Trading dashboard widget — no email sent (STAGE3-042 / UC_5.5 v1.8). | |
| 2026-08-12 | v1.5 | Q2: LIVE_DATA_UPGRADE vs MARKET_DATA product_id clarified — two distinct identifiers, explicit backend routing required; BR_5.7.2 routing table updated; §2 Trigger scope note updated | product_id = "MARKET_DATA" was the only routing key documented; LIVE_DATA_UPGRADE was unclear at webhook stage | Both are confirmed distinct. LIVE_DATA_UPGRADE = one-time onboarding checkout (Flow 3F Option B → checkout initiation). MARKET_DATA = recurring subscription and reactivation (webhook callback to Process Payment Webhook). Backend MUST configure explicit routing for both to avoid broken flows. | QnA STAGE3-033 confirmed 2026-08-12 |
Glossary
For all shared project terminology, refer to: Project Glossary.
UC_5.7 — Flow 3G: Market Data Payment (Futures Only)
1. Overview
| Field | Content |
|---|---|
| ID | UC_5.7 |
| Use Case | Flow 3G — Market Data Payment |
| Description | This UC covers two coupled payment-handling paths for Futures-only market data add-on billing. Sub-flow A (Initial Payment Confirmation — Flow 3G): Triggered when the payment processor sends a webhook after the trader completes the Option B checkout initiated by Flow 3F. The backend Process Payment Webhook endpoint ingests the webhook first — it extracts customer_vault_id, updates market_data_paid_until = current_date + 1 Month, audits to the invoices table, and pushes NEW_PAYMENT_SUCCESS to Zapier. Zapier Flow 3G then sets setup_status = 'Complete' and market_data_billable = True, and re-evaluates the dual aggregation gate — if contract_status = 'Signed', Flow 3H (live provisioning) is triggered. Sub-flow B (Recurring Monthly Billing Failure — Flow 22 failure path): Triggered via the INVOICE_PAYMENT_FAILED event pushed by Middleware to Zapier when NMI recurring charge fails. The End-of-Month hard check (Day 0) calls POST /toggle-market-data to disable additional exchange feeds (NYMEX, CBOT, COMEX) via Rithmic API, keeps the base CME feed active (firm-paid), sets market_data_billable = False, and sends the Data_Feed_Downgraded email. The trader may reactivate via the Dashboard "Reactivate" button (POST /toggle-market-data, enable_data: true) or purchase new add-ons via "Manage Add-ons" (POST /execute-checkout). |
| Zapier Flow | Flow 3G (Market Data Payment Handler — Futures Only) · Flow 22 (Monthly Data Fee Billing failure path) |
| Backend Endpoint | Process Payment Webhook (POST — ingests NMI/T365 webhook, routes by product_id, sets market_data_paid_until, pushes NEW_PAYMENT_SUCCESS) · POST /toggle-market-data (Rithmic feed toggle: disable on EOM hard check; re-enable on Reactivate) · POST /generate-invoices (Middleware monthly batch — initiates Sub-flow B) · POST /execute-checkout (Dashboard Manage Add-ons re-purchase) · GET /market-data-status (read feed status per exchange) |
| Zapier Table | Users table (setup_status, market_data_billable, market_data_flags JSON, market_data_paid_until, Last_Data_Payment_Status, customer_vault_id) |
| 3rd Party | Zapier (Flow 3G, Flow 22) · NMI / T365 (payment vault charge; customer_vault_id saved on first payment) · Rithmic API (feed enable/disable via Toggle Market Data endpoint) · AWS SES (Urgent_Data_Payment_Required, Data_Feed_Downgraded, Monthly_Data_Invoice_Available emails) |
Scope note — Futures only: Both sub-flows apply exclusively to
Asset_Class = 'Futures'traders. Forex traders havesetup_status = 'N/A'and are not in themarket_data_billable = Truecohort.
Scope note — two billing contexts: Sub-flow A is a one-time initial payment confirmation at the start of live phase (triggered by Flow 3F Option B). Sub-flow B is the recurring monthly billing failure path (triggered by Flow 22 scheduled job).
Scope note — payment webhook routing: The payment processor webhook does NOT go directly to Zapier. It hits the backend
Process Payment Webhookendpoint first, which routes byproduct_id. The backend MUST configure explicit routing for BOTH product identifiers used in the market data billing pipeline — they are distinct and operate at different pipeline stages (confirmed STAGE3-033):
product_idvaluePipeline stage Context 'LIVE_DATA_UPGRADE'Checkout initiation — Flow 3F Option B Used when Flow 3F calls POST /initiate-checkoutto generate the one-time onboarding payment link for the trader. This is theproduct_idthe payment gateway receives at checkout creation.'MARKET_DATA'Payment webhook callback — Flow 3G / Flow 22 Used when the payment gateway sends the webhook to Process Payment Webhookafter successful payment. Backend routes on this identifier to setmarket_data_paid_until = current_date + 1 Monthand pushNEW_PAYMENT_SUCCESSto Zapier. Also used for recurring monthly billing (Flow 22) and reactivation payments.Why both must be routed:
LIVE_DATA_UPGRADEis set by Stack Trading at checkout initiation;MARKET_DATAis the webhook-stage identifier in the payment gateway's response. If backend only handlesMARKET_DATA, onboarding traders who pay viaLIVE_DATA_UPGRADEwill have their webhook unrecognised —setup_statusstays'Pending_Payment'permanently and Flow 3H is never triggered. If backend only handlesLIVE_DATA_UPGRADE, recurring monthly billing viaMARKET_DATAwill fail to updatemarket_data_paid_until— traders lose feeds incorrectly. (Source: RFQ_ Stack Trading Prop Tech V7.pdf §Process Payment Webhook lines 1335–1373; QnA STAGE3-033 confirmed 2026-08-12)
Scope note —
market_data_flagsvsmarket_data_billable: The Users table schema (zapier_v7_full.txt line 339) definesmarket_data_flags (JSON/Object)as the authoritative field storing per-exchange entitlement state.market_data_billable(Boolean) is the Zapier operational flag that controls Flow 22 billing inclusion.market_data_paid_until(Date) is set by the backend on each successful MARKET_DATA payment and read byGET /market-data-statusto returnActive/Inactive/Availableper feed. All three coexist.
2. Trigger
Sub-flow A — Flow 3G (Initial Option B Payment Confirmation): Two-step trigger chain:
- Payment processor (NMI / T365) sends payment webhook to the backend
Process Payment Webhookendpoint. Backend extractscustomer_vault_id, routes onproduct_id = "MARKET_DATA", setsmarket_data_paid_until = current_date + 1 Month, inserts record toinvoicestable withfee_type = 'MARKET_DATA_ADDON', then pushesNEW_PAYMENT_SUCCESSevent to Zapier. - Zapier Flow 3G triggers on the
NEW_PAYMENT_SUCCESSevent, readsaddon_idsfrom the event metadata (passed through from NMI/T365 custom metadata fields), and executes the DB writes and gate check.
Note: addon_ids and product_id metadata MUST be configured on NMI/T365 to pass through the payment payload to the webhook catcher, so both backend and Zapier can parse the add-on selection. (Source: RFQ_ Stack Trading Prop Tech V7.pdf lines 1555–1558)
Sub-flow B — Flow 22 failure path (Recurring Monthly Billing Failure): Two-stage trigger:
INVOICE_PAYMENT_FAILEDevent pushed by Middleware to Zapier when NMI recurring charge againstcustomer_vault_idfails during the monthly billing run (~3 days before EOM).- End-of-Month hard check (Day 0 scheduled job): query SQL for
Market_Data_Billable = True AND Last_Data_Payment_Status = Failed→ proceeds to feed deactivation.
3. Pre-conditions
Sub-flow A:
Asset_Class = 'Futures'foruser_id.- Flow 3F Option B has been executed:
setup_status = 'Pending_Payment'in Users table. POST /initiate-checkoutwas called in Flow 3F;payment link was emailed to traderpayment completed on the Stack Trading dashboard (no email sent — STAGE3-042 / UC_5.5 v1.8 2026-08-14).- Trader has completed the checkout on the dashboard payment widget.
- Payment processor sends webhook to backend
Process Payment Webhookendpoint. - Backend routes on
product_id = "MARKET_DATA"and pushesNEW_PAYMENT_SUCCESSto Zapier.
Sub-flow B:
Asset_Class = 'Futures'foruser_id.market_data_billable = TrueandStatus = 'Active'in Users table.- Flow 22 monthly billing run has executed; NMI charge against
customer_vault_idhas failed. - Middleware has pushed
INVOICE_PAYMENT_FAILEDevent to Zapier. - End-of-Month Day 0 scheduled job has detected
Last_Data_Payment_Status = Failed.
4. Post-conditions
Sub-flow A — On payment success:
market_data_paid_until = current_date + 1 Monthset by backend (before Zapier fires).setup_status = 'Complete'in Users table (set by Zapier Flow 3G).market_data_billable = Truein Users table (set by Zapier Flow 3G).invoicestable: new record inserted withfee_type = 'MARKET_DATA_ADDON',status = 'paid'.- Aggregation gate evaluated: IF
contract_status = 'Signed'→ Flow 3H (UC_5.8) triggered via internal webhook. - IF
contract_status ≠ 'Signed': Zap terminates; Flow 3H triggered by Flow 3E when contract is signed.
Sub-flow A — On Reactivation payment success (trader paying overdue invoice):
Process Payment Webhookreceives webhook withproduct_id = 'MARKET_DATA'.- Middleware executes a single atomic DB transaction writing ALL of the following simultaneously:
market_data_paid_until = current_date + 1 MonthMarket_Data_Billable = TrueLast_Data_Payment_Status = NULL(cleared)
- System calls
POST /toggle-market-datawithenable_data = True→ Rithmic API re-enables NYMEX/CBOT/COMEX feeds. - Dashboard feed status returns to Green "Active"; "Reactivate" button disabled.
Note: The atomic reset of
Last_Data_Payment_Statusto NULL at reactivation is mandatory. If deferred, the next EOM Day 0 hard check readsMarket_Data_Billable = True AND Last_Data_Payment_Status = 'Failed'and re-deactivates feeds despite the trader having paid — a State-Machine Lockout bug. See BR_5.7.13.
Sub-flow B — On initial payment failure notification (before EOM hard check):
Last_Data_Payment_Status = Failedflagged in DB.Urgent_Data_Payment_Requiredemail sent to trader via AWS SES.- Ops Slack notification sent.
- Feeds remain active during grace period.
Sub-flow B — On End-of-Month hard check (payment failure confirmed):
POST /toggle-market-datacalled: Rithmic API disables additional exchange feeds (NYMEX, CBOT, COMEX). Base CME feed NOT toggled — remains active.market_data_billable = Falsein Users table.- Feed status transitions to
Inactive_Hold— visible in Dashboard as Grey "Paused" badge. Data_Feed_Downgradedemail sent to trader via AWS SES.- Trader may reactivate via Dashboard (see §6 Alternative Flow).
5. Basic Flow
Sub-flow A — Flow 3G: Initial Option B Payment Confirmation
- Payment processor sends webhook to backend
Process Payment Webhookendpoint. - Backend ingests webhook:
- 2a. IF NMI payload: extract and save
customer_vault_idto Users table. - 2b. Extract
product_idanduser_idfrom payload. - 2c. Route on
product_id = "MARKET_DATA": execute single atomic DB transaction writing:market_data_paid_until = current_date + 1 Monthmarket_data_flagsJSON column: write per-exchange Active/Inactive flags by parsingaddon_idsfrom gateway metadata (e.g.NYMEX_Bundle → nymex: true,CBOT_Bundle → cbot: true). This is the authoritative write formarket_data_flags— Zapier does NOT write this field (confirmed STAGE3-047). All three fields written atomically: partial writes not permitted.Last_Data_Payment_Status = NULL(if this is a Reactivation payment; see BR_5.7.13)Market_Data_Billable = True(if this is a Reactivation payment; see BR_5.7.13)
- 2d. Insert record to
invoicestable:fee_type = 'MARKET_DATA_ADDON',status = 'paid'. - 2e. Push
NEW_PAYMENT_SUCCESSevent (with full metadata includingaddon_ids) to Zapier. - 2f. Broadcast
PAYMENT_RESULTevent (status = SUCCESS) via WebSocket/Redis to client.
- 2a. IF NMI payload: extract and save
- Zapier Flow 3G triggers on
NEW_PAYMENT_SUCCESSevent. - Zapier UPDATE Users table WHERE
user_id = event.user_id:setup_status = 'Complete'market_data_billable = True
- Aggregation gate check: Zapier queries
contract_statusWHEREuser_id.- IF
contract_status = 'Signed'→ fire internal webhook to trigger Flow 3H (UC_5.8). - ELSE → Zap terminates; wait for Flow 3E (contract signing will re-evaluate the gate).
- IF
Sub-flow B — Flow 22 Monthly Billing Failure Path
Phase 1 — Monthly billing run (~3 days before EOM):
- Scheduled job triggers Flow 22. Middleware calls
POST /generate-invoiceswithbilling_cycle_date. - Middleware queries DB:
Status = 'Active' AND Asset_Class = 'Futures' AND Market_Data_Billable = True. - For each trader in scope: calculate
Invoice_Amountusing tiered formula (per BR_5.7.6). - Query DB for active MIDs. Retrieve
customer_vault_idarray. Execute batch NMI charges using Weighted Round-Robin algorithm (weighted by remaining MID capacity). - IF charge fails:
- Flag
Last_Data_Payment_Status = Failedin DB. - Push
INVOICE_PAYMENT_FAILEDevent to Zapier. - Zapier sends
Urgent_Data_Payment_Requiredemail to trader via AWS SES + Ops Slack notification. - Feeds remain active during grace period.
- Flag
Phase 2 — End-of-Month hard check (Day 0 scheduled job):
- Scheduled job runs on last day of month.
- Query SQL:
Market_Data_Billable = True AND Last_Data_Payment_Status = Failed. - For each trader in this state:
- Call Middleware
POST /toggle-market-datawithuser_id,enable_data = False→ Middleware calls Rithmic Broker API to disable additional feeds (NYMEX/CBOT/COMEX) only. Base CME feed NOT toggled. - UPDATE Users table:
market_data_billable = False. - Feed status becomes
Inactive_Hold. - Send
Data_Feed_Downgradedemail to trader via AWS SES.
- Call Middleware
6. Alternative Flow
-
[Contract already signed when Sub-flow A payment webhook arrives]
contract_status = 'Signed'found at gate check Step 5.- Flow 3H triggered immediately in this Zap execution with
market_data_billable = True. - Flow 3H provisions Professional Market Data + Add-ons via Rithmic API.
-
[Contract not yet signed when Sub-flow A payment webhook arrives]
contract_status ≠ 'Signed': Zap terminates.- When Flow 3E later processes the signed contract, it finds
setup_status = 'Complete'and triggers Flow 3H at that time.
-
[Trader reactivates feeds after Sub-flow B downgrade — Dashboard Reactivate button]
- Dashboard shows feed status as
Inactive_Hold(Grey "Paused" badge). - Trader clicks "Reactivate" button (enabled only when status =
Inactive_Hold). - Frontend calls
POST /toggle-market-datawithenable_data: true. - On success: "Success" toast displayed; connection credentials card refreshed; feed status returns to Green "Active".
- Middleware simultaneously executes atomic DB transaction:
market_data_paid_until = current_date + 1 Month,Market_Data_Billable = True,Last_Data_Payment_Status = NULL. All three writes in one transaction — partial writes not permitted. (See BR_5.7.13) - (Source: RFQ_ Website and Dashboard Implementation V7.pdf Market Data Management lines 599–608)
- Dashboard shows feed status as
-
[Trader purchases new/additional add-ons — Dashboard Manage Add-ons button]
- Trader clicks "Manage Add-ons" (Button 2, distinct from Reactivate).
- Frontend calls
GET /market-data-products(authenticated) — returns only products the trader does NOT currently have active. - Trader selects desired exchange feeds; 1-Click Confirmation Modal rendered ("Total: $[Amount]", "Pay with vaulted card").
- Frontend calls
POST /execute-checkoutwithproduct_id = 'MARKET_DATA',addon_ids = [selected_ids],payment_method = 'CC',user_id. - Backend executes charge against
customer_vault_id(no re-entry of card details). - On success: "Feeds Activated" toast; account state refreshed.
- Payment webhook → backend
Process Payment Webhook→ setsmarket_data_paid_until = current_date + 1 Month→ pushesNEW_PAYMENT_SUCCESS→ Zapier re-setsmarket_data_billable = Trueif needed. - (Source: RFQ_ Website and Dashboard Implementation V7.pdf lines 607–635)
-
[Level 3+ trader promotion — firm resumes full data cost coverage]
- At Level 3 promotion,
Promotion_Level_3Klaviyo event fires — includes "data fee refund status". - Backend calculates refundable amount via
GET /financial/calculate-data-refund: sumsinvoices.amount WHERE fee_type = 'MARKET_DATA_BASE' AND status = 'paid'for Level 1 & 2 period. Excludes add-on fees (non-refundable). - After Level 3 promotion, Market Data Lifecycle Disclosure confirms: "Level 3 to Level 24: The Firm pays 100% of data costs."
market_data_billabletransitions toFalseat promotion. Exact Zapier flow step setting this is[MISSING]from Flow 3G source — likely in the Level-Up/Promotion flow.- (Source: RFQ_ Website and Dashboard Implementation V7.pdf lines 342–350; RFQ_ Stack Trading Prop Tech V7.pdf §Calculate Data Refund lines 1985–2000; Zapier Integration V7.pdf Promotion_Level_3 line 756)
- At Level 3 promotion,
7. Exceptional Flow
-
[Sub-flow A —
NEW_PAYMENT_SUCCESSevent received for unknownuser_id][MISSING]— no handling documented if the event contains auser_idnot in the Users table. Should Zapier filter halt silently or alert Ops?
-
[Sub-flow A — duplicate
NEW_PAYMENT_SUCCESSevent (re-delivery)]- Backend enforces
provider_event_iddeduplication: if Event_ID already exists in DB → HALT (zapier_v7_full.txt line 872). - Zapier-level dedup:
[MISSING]— whether Flow 3G separately checksprovider_event_idbefore re-writingsetup_statusis not documented in zapier source.
- Backend enforces
-
[Sub-flow A — payment processor sends webhook but backend
Process Payment Webhookis unreachable][MISSING]— no retry or dead-letter queue documented for failed webhook delivery to the backend endpoint. Trader'smarket_data_paid_untilandsetup_statuswould not be updated.
-
[Sub-flow B —
POST /toggle-market-datacall to Rithmic fails on EOM Day 0][MISSING]— if the Rithmic API call to disable add-on feeds fails, the trader continues receiving feeds without payment. No retry or Ops escalation path documented for this specific failure.
-
[Sub-flow B — trader has no vaulted
customer_vault_idfor Manage Add-ons re-purchase][MISSING]— if the trader's vaulted card is expired or deleted,POST /execute-checkoutfails on the vaulted charge. No fallback for entering a new payment method in this context is documented.
-
[Sub-flow B —
INVOICE_PAYMENT_FAILEDevent never received (Middleware silent failure)][MISSING]— if Middleware fails to push the event, Zapier never fires theUrgent_Data_Payment_Requiredemail. The only safety net is the Day 0 hard check. No monitoring alert for missing events is documented.
8. Business Rules
BR_5.7.1: Futures-Only Scope
Flow 3G and the Flow 22 failure path apply exclusively to Asset_Class = 'Futures' traders. Forex traders are not subject to Rithmic market data billing.
(Source: Zapier Integration V7.pdf Flow 3G line 1251; Flow 22 line 2179)
BR_5.7.2: Backend Processes Payment Webhook Before Zapier — Dual product_id Routing Required
The payment processor webhook hits the backend Process Payment Webhook endpoint first — not Zapier directly. The backend:
- Validates the webhook signature.
- Extracts and saves
customer_vault_id(if NMI payload). - Routes on
product_id: for"MARKET_DATA"→ setsmarket_data_paid_until = current_date + 1 Month. - Inserts
invoicesrecord withfee_type = 'MARKET_DATA_ADDON'. - Pushes
NEW_PAYMENT_SUCCESSevent to Zapier. - Broadcasts
PAYMENT_RESULTto client via WebSocket/Redis.
Zapier Flow 3G triggers on the NEW_PAYMENT_SUCCESS event, not directly on the payment processor webhook.
Mandatory dual routing — LIVE_DATA_UPGRADE AND MARKET_DATA (confirmed STAGE3-033):
LIVE_DATA_UPGRADE and MARKET_DATA are two distinct identifiers operating at different pipeline stages. Backend MUST configure explicit handling for both:
product_id | When set | Who sets it | What backend must do on receipt |
|---|---|---|---|
'LIVE_DATA_UPGRADE' | At checkout initiation | Flow 3F calls POST /initiate-checkout | Route to onboarding payment processing; update setup_status-related fields via Flow 3G |
'MARKET_DATA' | At payment webhook callback | Payment gateway sends in webhook | Set market_data_paid_until = current_date + 1 Month; push NEW_PAYMENT_SUCCESS to Zapier; handle reactivation atomic reset (BR_5.7.13) |
Risk if routing is incomplete:
- If backend only handles
MARKET_DATA: onboarding payment webhook withproduct_id = 'LIVE_DATA_UPGRADE'is not recognised →setup_statusstays'Pending_Payment'indefinitely → Flow 3H never triggered → trader permanently blocked from live provisioning. - If backend only handles
LIVE_DATA_UPGRADE: recurring monthlyMARKET_DATApayments fail to updatemarket_data_paid_until→ feeds incorrectly deactivated on the next EOM hard check.
(Source: RFQ_ Stack Trading Prop Tech V7.pdf §Process Payment Webhook lines 1335–1373; QnA STAGE3-033 confirmed 2026-08-12)
BR_5.7.3: Zapier Flow 3G Writes setup_status and market_data_billable
After the backend pushes NEW_PAYMENT_SUCCESS, Zapier Flow 3G writes two fields:
setup_status = 'Complete'— satisfies the setup leg of the Flow 3H dual aggregation gate.market_data_billable = True— enrolls the trader in monthly Flow 22 billing.
Both writes occur before the aggregation gate check.
(Source: Zapier Integration V7.pdf Flow 3G lines 1254–1261)
BR_5.7.4: Flow 3H Provisioning Branches on market_data_billable
When Flow 3H (UC_5.8) is triggered after Sub-flow A, provisioning branches on this flag:
market_data_billable = True: Provision Professional Market Data + Add-ons via Rithmic API.market_data_billable = False(Option A traders): Provision Standard Data (Firm Covered) as Professional.
(Source: Zapier Integration V7.pdf Flow 3H lines 1281–1283)
BR_5.7.5: Two-Stage Failure Response — Grace Period Then Hard Deactivation
Monthly billing failure does NOT immediately deactivate feeds:
| Stage | Timing | Action |
|---|---|---|
| Phase 1 — Soft failure | ~3 days before EOM (billing run) | Flag Last_Data_Payment_Status = Failed; send Urgent_Data_Payment_Required email + Ops Slack; feeds remain active |
| Phase 2 — Hard deactivation | Day 0 (last day of month) | Disable NYMEX/CBOT/COMEX via POST /toggle-market-data; set market_data_billable = False; feed status = Inactive_Hold; send Data_Feed_Downgraded email |
The grace period gives the trader time to update payment before hard deactivation.
(Source: Zapier Integration V7.pdf Flow 22 lines 2192–2204)
BR_5.7.6: Base CME Feed Preserved on Deactivation
When Phase 2 hard deactivation runs, ONLY add-on feeds (NYMEX, CBOT, COMEX) are disabled. The base CME feed (1 Level 2 feed, Base_CME_Data_Cost = $140/month) remains active — firm-paid regardless of trader payment status.
The POST /toggle-market-data call targets add-on feeds only.
(Source: Zapier Integration V7.pdf Flow 22 lines 2200–2203)
BR_5.7.7: Inactive_Hold Status and Reactivate Button
After EOM hard deactivation, the trader's feed state becomes Inactive_Hold. The Dashboard shows a Grey "Paused" badge. The "Reactivate" button (Button 1 in Market Data Management) is only enabled when status = Inactive_Hold.
- Reactivate action:
POST /toggle-market-datawithenable_data: true→ Middleware calls Rithmic API to re-enable feeds. - On success: "Success" toast; connection credentials card refreshed.
This is distinct from the "Manage Add-ons" button (Button 2), which purchases new/additional feeds via POST /execute-checkout.
(Source: RFQ_ Website and Dashboard Implementation V7.pdf Market Data Management lines 599–608; RFQ_ Stack Trading Prop Tech V7.pdf Toggle Market Data endpoint lines 1218–1222)
BR_5.7.8: market_data_flags, market_data_billable, and market_data_paid_until — Three Coexisting Fields
| Field | Type | Set by | Purpose |
|---|---|---|---|
market_data_flags (JSON/Object) | JSON | Node.js middleware only — written atomically at Process Payment Webhook by parsing addon_ids from gateway metadata (confirmed STAGE3-047). Zapier does NOT write this field. | Per-exchange entitlement state; evaluated by GET /market-data-status to return Active/Inactive/Available per feed (CME, CBOT, NYMEX, COMEX) |
market_data_billable (Boolean) | Boolean | Zapier (Flow 3F/3G/22) | Controls whether Flow 22 includes this trader in monthly invoice batch |
market_data_paid_until (Date) | Date | Backend (Process Payment Webhook) | Tracks payment expiry per billing cycle; used with market_data_flags by GET /market-data-status |
Security:
Process Payment Webhookenforces three-layer webhook security per BR_5.7.12 (HMAC/JWS signature verification + IP allowlisting + idempotency viaprovider_event_id+correlation_id). The three-field atomic write is part of the same secure transaction.
(Source: Zapier Integration V7.pdf Users table schema line 339; RFQ_ Stack Trading Prop Tech V7.pdf §Get Market Data Status lines 1493–1498; §Process Payment Webhook line 1360)
BR_5.7.9: Tiered Monthly Invoice Formula
Flow 22 applies the following tiered formula when generating invoices for market_data_billable = True traders:
| Trader level | Invoice formula |
|---|---|
| Level 1 & Level 2 (Provisional / Math) | Invoice_Amount = Total_Market_Data_Cost (full cost — firm does NOT cover CME base at Level 1/2) |
| Level 3+ (Senior) | Invoice_Amount = Total_Market_Data_Cost - Base_CME_Data_Cost ($140) (firm covers CME base from Level 3+) |
Consistent with GET /financial/calculate-data-refund: at Level 3 promotion, backend refunds only MARKET_DATA_BASE fees paid during Level 1 & 2 (confirming those were trader-paid).
Source resolution:
Zapier Integration V7.pdfFlow 22 lines 2186–2187 showed onlyTotal − Base_CME(shorthand for Level 3+ formula). The detailed "Perks & Batch Process Endpoints" section in the same Zapier V7 document explicitly states the tiered logic, consistent withRFQ_ Stack Trading Prop Tech V7.pdflines 1585–1590. Conflict resolved — confirmed by client 2026-08-10 (QnA STAGE3-013).
(Source: Zapier Integration V7.pdf §Perks & Batch Process Endpoints — tiered billing logic; RFQ_ Stack Trading Prop Tech V7.pdf lines 1575–1595; QnA STAGE3-013 confirmed 2026-08-10)
BR_5.7.10: Level 3 Promotion — Firm Resumes Full Data Cost Coverage and Refund
At Level 3 promotion:
- Market Data Lifecycle Disclosure: "Level 3: Trader is 100% reimbursed for Level 1 and 2 market data costs incurred. Level 3 to Level 24: Firm pays 100% of data costs."
- Backend endpoint
GET /financial/calculate-data-refundcalculates the refundable amount:SUM(invoices.amount) WHERE fee_type = 'MARKET_DATA_BASE' AND status = 'paid'for the trader's Level 1 & 2 period. Add-on fees (NYMEX/CBOT/COMEX) and platform fees are excluded — non-refundable. - After Level 3,
market_data_billabletransitions toFalse. The exact Zapier flow step that sets this is[MISSING]from Flow 3G source — likely in the Level-Up/Promotion flow (UC for level promotion, not UC_5.7).
(Source: RFQ_ Website and Dashboard Implementation V7.pdf Market Data Lifecycle Disclosure lines 342–350; RFQ_ Stack Trading Prop Tech V7.pdf §Calculate Data Refund lines 1985–2000)
BR_5.7.11: Universal Metadata Mandate — All Payment Gateways
⚠️ Source note: "T365" and "CR-20260730-001" referenced in the original audit question are not documented or mentioned anywhere in the V7 architecture specifications. Their specific payload schema and webhook auth cannot be verified from current source materials. The following mandate applies to ALL gateways per V7 §1.3 Vendor Requirements & Scalability — including any future replacement aggregator.
Regardless of which payment gateway processes a transaction (NMI, Triple-A, Skrill, Nomupay, EBANX, Dusupay, or any future/replacement gateway), the custom metadata attached to each payment MUST be structurally identical. The middleware Process Payment Webhook endpoint and downstream Zapier automation chains (Flow 1, Flow 22) are hardcoded to parse the exact same custom fields:
| Field | Type | Purpose |
|---|---|---|
user_id | UUID | Maps transaction to correct PostgreSQL profile |
product_id | String | Identifies transaction type ('EVAL_L1', 'LIVE_DATA_UPGRADE', 'MARKET_DATA', 'RESET', 'REBUY') |
addon_ids | Array | Purchased premium exchange feeds (e.g. ['NYMEX_Bundle', 'CBOT_Bundle']) |
If a gateway does not natively support custom metadata dictionaries, or fails to pass these exact keys through its payment webhook payload, Process Payment Webhook will fail to parse the payment and automated onboarding/billing systems will break entirely.
(Source: RFQ_ Stack Trading Prop Tech V7.pdf lines 1555–1558; Zapier Integration V7.pdf line 2691; V7 §1.3 Vendor Requirements & Scalability; QnA STAGE3-032 confirmed 2026-08-11)
BR_5.7.12: Webhook Security Mandate — All Payment Gateways
Per V7 §1.3 Vendor Requirements & Scalability, ALL payment gateways integrated into the Stack Trading ecosystem must comply with the following security standards:
| Requirement | Detail |
|---|---|
| Signed Webhook Verification (HMAC/JWS) | Middleware receiver endpoint MUST cryptographically validate the incoming payload signature using a securely stored gateway secret — comparable to Veriff and Trustpilot webhook validation |
| IP Address Allowlisting | When supported by the provider, inbound IP ranges MUST be explicitly allowlisted at the Cloudflare reverse proxy/WAF or AWS Ingress layer to block spoofed/malicious traffic |
| Idempotency Enforcement | Each webhook MUST carry both a unique provider_event_id (or transactional event_id) AND a correlation_id — both are required for the DB event-log to prevent double-charging or duplicate account provisioning on gateway re-transmission |
The backend Process Payment Webhook endpoint enforces idempotency: if provider_event_id already exists in DB → HALT, no re-processing.
(Source: Zapier Integration V7.pdf lines 872, 2700; V7 §1.3 Vendor Requirements & Scalability; QnA STAGE3-032 confirmed 2026-08-11)
BR_5.7.13: Atomic Reset of Last_Data_Payment_Status on Reactivation Payment
When a trader in Inactive_Hold state (EOM hard-deactivated) pays their overdue invoice, the backend Process Payment Webhook endpoint MUST execute a single atomic DB transaction that writes ALL of the following simultaneously:
| Field | Value set | Required |
|---|---|---|
market_data_paid_until | current_date + 1 Month | YES |
Market_Data_Billable | True | YES |
Last_Data_Payment_Status | NULL (or 'Paid'/'Success') | YES — atomic with above |
Simultaneously, system calls POST /toggle-market-data with enable_data = True to re-enable NYMEX/CBOT/COMEX feeds via Rithmic API.
Why atomic reset is mandatory — State-Machine Lockout prevention:
The EOM Day 0 hard check queries: Market_Data_Billable = True AND Last_Data_Payment_Status = 'Failed'.
If Last_Data_Payment_Status is NOT cleared at reactivation:
- At next EOM:
Market_Data_Billable = True(restored) ANDLast_Data_Payment_Status = 'Failed'(stale) → hard check condition is met again. - System re-deactivates the trader's feeds despite them having paid — a false double-deactivation.
Partial writes are not permitted. All three fields must succeed or the transaction rolls back entirely.
(Source: QnA STAGE3-031 confirmed 2026-08-11)
9. Wireframe / UI
WBS status_design = 'Done'. Four screens referenced in WBS mapping_design:
| Screen | Figma Reference | Wireframe file | Context |
|---|---|---|---|
| Confirm market data add-on | Figma node 1-29891 | Stage 3: Total wireframe/Flow 3G: Market data checkout.png | 1-Click Confirmation Modal — "Total: $[Amount]", "Pay with vaulted card" |
| Change Payment | Figma node 1-30011 | — | Update payment method before re-attempting |
| Processing | Figma node 1-30247 | Stage 3: Total wireframe/Flow 3G: Payment loading.png | Payment processing interstitial |
| Success | Figma node 1-30345 | — | "Feeds Activated" confirmation |
Additional Flow 3G wireframes (error/edge states):
| Screen | Wireframe file | Context |
|---|---|---|
| Payment fail popup | Stage 3: Total wireframe/Flow 3G: Payment fail popup.png | Payment failure modal — error message + retry/change payment options |
| Market price updated popup | Stage 3: Total wireframe/Flow 3G: Popup Market price updated .png | Price-change notification popup — shown when market data price changes before confirmation |
| Payment methods unavailable popup | Stage 3: Total wireframe/Flow 3G: Popup Payment methods unavailble.png | System popup when no payment method is available to process |
All wireframe files are located in: References/Wireframe/Stage 3/Stage 3: Total wireframe/
The backend webhook receipt (Sub-flow A trigger) has no trader-facing UI — it is a server-to-server event. The Dashboard Market Data Management panel displays feed status (Green "Active" / Grey "Paused") and hosts both the Reactivate and Manage Add-ons buttons.
(Source: WBS mapping_design UC_5.7; RFQ_ Website and Dashboard Implementation V7.pdf lines 596–635)
10. Screen Description and Business Rules
Screen 1: 1-Click Confirmation Modal (Confirm Market Data Add-on)
Rendered when trader selects add-ons via "Manage Add-ons" button (Button 2). Overlays the Dashboard.
| Element | Type | Behavior |
|---|---|---|
| Feed list | Read-only | Selected exchange bundles with individual prices |
| Total | Read-only | "Total: $[Amount]" — from GET /market-data-products pricing |
| Payment method | Read-only | "Pay with vaulted card [last 4 digits]" |
| CTA — Confirm | Primary button | Calls POST /execute-checkout with product_id = 'MARKET_DATA', addon_ids, payment_method = 'CC' |
| Change Payment Method | Text link | Opens Screen 2 |
Business rule: Backend executes against stored customer_vault_id. Frontend must NOT prompt re-entry of card details.
(Source: RFQ_ Website and Dashboard Implementation V7.pdf lines 614–635)
Screen 2: Change Payment (Update Payment Method)
Displayed when trader clicks "Change Payment Method" from Screen 1.
[MISSING] — dashboard_v7_full.txt line 697 references this screen but the continuation is truncated. Full behavior [MISSING] from source.
Screen 3: Processing (Payment Interstitial)
Loading state while POST /execute-checkout is in flight. Pattern consistent with checkout Step 7 (dashboard_v7_full.txt line 509: "Headline (H4): Processing Payment").
Wireframe: Stage 3: Total wireframe/Flow 3G: Payment loading.png
Screen 4: Success (Feeds Activated Confirmation)
| Element | Type | Behavior |
|---|---|---|
| Toast | Success | "Feeds Activated" |
| Account state | Auto-refresh | New feeds shown as "Active"; Data Feed Status badge → Green |
(Source: RFQ_ Website and Dashboard Implementation V7.pdf lines 628–635)
Screen 5: Payment Fail Popup
Wireframe: Stage 3: Total wireframe/Flow 3G: Payment fail popup.png
Displayed when POST /execute-checkout returns a payment failure. Trader is offered retry or change payment method options.
Screen 6: Market Price Updated Popup
Wireframe: Stage 3: Total wireframe/Flow 3G: Popup Market price updated .png
Displayed when market data pricing changes between the time the trader opens the confirmation modal and the time they confirm. Frontend must re-fetch pricing and display the popup before allowing re-confirmation.
Screen 7: Payment Methods Unavailable Popup
Wireframe: Stage 3: Total wireframe/Flow 3G: Popup Payment methods unavailble.png
Displayed when no payment method is available (e.g., customer_vault_id IS NULL and no fallback active). Trader prompted to add a payment method.
END OF UC_5.7