SRS: Stage 3 KYC & Live Onboarding — UC_5.4: Flow 3C Dots Payout Profile
| Field | Value |
|---|---|
| BA in Charge | linh.nguyen34 |
| Date Created | 2026-08-07 |
| Version | v1.8 |
| Last Updated | 2026-08-25 — CR-20260825-001: Sub-flow A Step 5 corrected to use Veriff legal_name (not SIM first_name/last_name); Step 6 corrected to PUT /v2/users/{id}/addresses (not "Submit Compliance"); Sub-flow B trigger corrected to user.updated + GET re-fetch + 5-field check; BR_5.4.5 updated. |
| Document References | Zapier Integration V7.pdf (Flow 3A lines 1062–1085; Flow 3C lines 1158–1175) · RFQ_ Stack Trading Prop Tech V7.pdf (§Process Veriff Handoff, lines 754–782) · CR-20260720-004 (Freshdesk replaces Zendesk — not applicable to this UC) |
UC Index
| UC_ID | Use Case Name | Business Description |
|---|---|---|
| UC_5.4 | Flow 3C — Dots Payout Profile | After Veriff APPROVED,Process Veriff Handoff (Flow 3B / UC_5.2) runs a 3-step Dots payee creation: (1) POST /v2/users with SIM data → stores dots_payee_id; (2) Submit Compliance Information with Veriff-extracted legal_name + address (pre-fills W-9/W-8BEN); (3) POST /v2/flows → flow_link → "Payout Profile Setup" email dispatched. Flow 3C then listens for the Dots Active and Payable webhook → sets payout_status = 'Approved' → evaluates three-way aggregation gate for Flow 3D. |
Changelog
| Date | Version | Updated item | Before | After | Notes |
|---|---|---|---|---|---|
| 2026-08-07 | v1 | Initial creation | — | Created SRS for UC_5.4 (Flow 3C — Dots Payout Profile) | First authoring pass |
| 2026-08-08 | v1.1 | Futures Dots path — §1 Scope note, §1 Overview, §3 Pre-conditions, §4 Post-conditions, §6 Alternative Flow | [MISSING] — Futures path undocumented; email behavior on existing Dots profile ambiguous | Flow 3A generates Dots hosted onboarding link for Futures traders; trader manually completes form, no auto-fill from Ironbeam. Email NOT sent for existing Dots profile — derived from source step 3 exit logic. | Source: Zapier Integration V7.pdf Flow 3A lines 1068–1075; RFQ_ Stack Trading Prop Tech V7.pdf §Process Veriff Handoff steps 3–6 |
| 2026-08-12 | v1.1 → v1.2 | §1 Scope note — Futures path | Futures traders use Ironbeam WLP portal + manual Dots entry | All traders now use Veriff (STAGE3-037 [CHR-46]). Futures traders auto-fill Dots from Veriff same as Forex. Ironbeam WLP branch removed. | STAGE3-037 confirmed 2026-08-12 |
| 2026-08-12 | v1.2 → v1.3 | §7 Sub-flow B — Dots suspension exceptional flow + §8 BR_5.4.8 / BR_5.4.9 | [MISSING] for Dots Suspended/Paused/Failed during Stage 3 | Confirmed: add Dots suspension webhook listener; set payout_status = 'Suspended'; Flow 3D blocked automatically; add payout_status == 'Approved' check to Flow 3H; dispatch Dots_Profile_Action_Needed email. | STAGE3-038 [CHR-44] confirmed 2026-08-12 |
| 2026-08-15 | v1.4 → v1.5 | §1 UC Index, §1 Description, §3 Pre-cond Sub-flow A, §4 Post-cond, §5 Steps 5-9, §6 Alt-flow, §7 Exceptional Flow | Sub-flow A called POST /payees with Veriff-extracted legal_name/address; institution_approval_status = 'Approved' -- Forex only; second-cycle path marked [MISSING] | 3-step Dots process: POST /v2/users SIM data → Submit Compliance Veriff data → POST /v2/flows → flow_link. Second-cycle (H-07): skip steps 5-7, set payout_status directly. Exc flows updated with STAGE3-082/083/084/085. | STAGE3-052/055/082/083/084/085 confirmed 2026-08-15 |
| 2026-08-14 | v1.3 → v1.4 | §1 Description, §1 Scope notes, §3 Pre-conditions, §4 Post-conditions, §1 Zapier Flow row | "Forex only" qualifier on Sub-flow A; Futures path via Flow 3A with manual Dots entry; Scope note labeled "Forex traders" | Sub-flow A now applies to ALL traders (Futures + Forex) — STAGE3-037 [CHR-46].identity_status and institution_approval_status set by Flow 3B (Veriff) for ALL traders, not Forex only. Futures path via Flow 3A + Ironbeam KYC link deprecated. | [CHR-46] / STAGE3-037 [CHR-46] |
Glossary
For all shared project terminology, refer to the single source of truth: Project Glossary.
<a id="UC_5.4"></a>
UC_5.4 — Flow 3C: Dots Payout Profile
1. Overview
| Field | Content |
|---|---|
| ID | UC_5.4 |
| Use Case | Flow 3C — Dots Payout Profile |
| Description | This UC covers two coupled sub-flows.Sub-flow A (Dots Payee Creation — ALL traders, inside Process Veriff Handoff / UC_5.2): Triggered when Veriff returns APPROVED for any trader. The 3-step creation process runs: (1) POST /v2/users with Veriff-extracted legal_name (split into first/last) + SIM contact fields (email, country_code, phone_number, metadata.internal_id) — must use Veriff name, NOT SIM registration name, because Dots IRS TIN matching runs against stored profile name (Dots bug, fix in progress as of 2026-08-25); (2) PUT /v2/users/{dots_payee_id}/addresses with Veriff-extracted normalized address — pre-fills W-9/W-8BEN address field on Dots Form UI (NOT PUT /compliance which signs and finalizes immediately); (3) POST /v2/flows (manage-payouts step) → flow_link. The flow_link is dispatched in the "Payout Profile Setup" email. Second-cycle logic: if dots_payee_id IS NOT NULL at APPROVED, all three steps are skipped and payout_status is set to 'Approved' directly (STAGE3-055). Sub-flow B (Payout Verification Handler — Flow 3C): When Dots fires a user.updated webhook, middleware immediately re-fetches GET /v2/users/{dots_payee_id} and validates all 5 health-check fields (status=verified, default_payout_method non-null, compliance.must_collect_1099=false, compliance.w8_ben_collected=true/skipped, compliance.flagged=false). On all-pass: sets payout_status = 'Approved' and evaluates the aggregation gate for Flow 3D. |
| Zapier Flow | |
| Backend Endpoint | Process Veriff Handoff (POST — fires Sub-flow A on Veriff APPROVED) |
| Zapier Table | Users table (dots_payee_id written by backend; payout_status = 'Approved' set by Flow 3C) |
| 3rd Party | Dots (payee creation API, hosted W-9/W-8BEN forms, payout routing) · Veriff (source of legal_name + address for all traders — STAGE3-037 [CHR-46]) · AWS SES (delivers Payout Profile Setup email) |
Scope note — Futures traders (UPDATED STAGE3-037 [CHR-46] 2026-08-12):
For Futures traders,All traders now use Veriff. Ironbeam waived manual KYC applications for all traders. Futures traders now go through Veriff (Flow 3B/UC_5.2) same as Forex traders, and thedots_payee_idcreation follows a different path from Forex. Flow 3A handles both asset classes: it setskyc_link = Ironbeam White Label Portal URLfor Futures, then calls the Dots API to generate a hosted onboarding link and emails both links to the trader. The trader manually completes the Dots-hosted form; there is no auto-fill from Ironbeam data.Process Veriff Handoffendpoint automatically creates the Dots payee profile using KYC-extractedlegal_nameandaddressfor all traders — no manual entry required. The Futures-specific scope note on manual Dots completion is obsolete. (Source: STAGE3-037 [CHR-46] confirmed 2026-08-12)
Scope note — All traders (UPDATED STAGE3-037 [CHR-46] 2026-08-12): All traders'
payout_statusis set to'Approved'by Flow 3C (this UC) after they complete the Dots onboarding. Theiridentity_statusandinstitution_approval_statusare set by Flow 3B (Veriff) — this applies to both Futures and Forex traders since all traders now go through Veriff (STAGE3-037 [CHR-46]). All three fields must be'Approved'before Flow 3D fires.
Scope note — Returnee Trader bypass (BR_5.1.11 / STAGE3-055/H-07 extended, 2026-08-18): For Returnee Traders (Branch B at Flow 3A —
identity_status = 'Approved'ANDdots_payee_id IS NOT NULLANDcontract_status = 'Signed'), Sub-flow A and Sub-flow B are both skipped entirely. Flow 3A Branch B setspayout_status = 'Approved'directly in one atomic DB write without calling the Dots API. No new Dots session is created; therefore Dots does NOT fire a new "Active and Payable" webhook for Returnee Traders. Flow 3C (this UC) is not triggered for the Returnee path.
2. Trigger
Sub-flow A — Dots Payee Creation:
Triggered as a synchronous step within the Process Veriff Handoff backend endpoint when Veriff returns verification_status = 'approved'. The backend processes the Veriff webhook, then immediately calls the Dots API if dots_payee_id IS NULL in the Users table.
Sub-flow B — Payout Verification Handler (Flow 3C):
Triggered when Dots sends a user.updated webhook. Middleware must NOT parse compliance fields directly from the webhook payload — instead, immediately re-fetch GET /v2/users/{dots_payee_id} and validate the 5-field health check on the response. This is the pattern confirmed by Dots (CR-20260825-001 2026-08-25).
3. Pre-conditions
Sub-flow A (Dots Payee Creation — ALL traders):
- Veriff webhook received with
verification_status = 'approved'for the trader's KYC session. - Backend has successfully validated the Veriff cryptographic payload signature (HMAC check).
legal_name,address, andkyc_countryhave been extracted from the Veriff payload and saved to Users table (UC_5.2 §5 Step 3).- SIM registration data (
first_name,last_name,email,country_code,phone_number) available in Users table from Stage 1/2 registration. - Applies to ALL traders (Futures and Forex) — STAGE3-037 [CHR-46].
Sub-flow B (Payout Verification Handler — Flow 3C):
- Dots payee profile exists for the trader (created via Sub-flow A for ALL traders — Veriff path).
- Trader has clicked the Dots white-labeled onboarding link and completed it.
- Trader has completed the Dots-hosted tax form (W-9 for US; W-8BEN for international) and linked a payout routing method.
- Dots has confirmed the profile is
Active and Payableand fired the webhook.
4. Post-conditions
Sub-flow A — On Dots payee creation (success — ALL traders, first cycle):
dots_payee_idstored in the Users table for thisuser_id.identity_status = 'Approved',institution_approval_status = 'Approved'written.payout_flow_link(fromPOST /v2/flows) stored for email dispatch.- "Payout Profile Setup" email sent to trader via AWS SES containing the personalized
flow_link.
Sub-flow A — Second cycle (dots_payee_id IS NOT NULL — H-07/STAGE3-055):
- Dots steps 4A-1 through 4A-3 skipped entirely.
identity_status = 'Approved',institution_approval_status = 'Approved',payout_status = 'Approved'all written directly.- No payout email dispatched.
- Aggregation check fires immediately.
Sub-flow B — On webhook received from Dots:
- Users table updated:
payout_status = 'Approved'foruser_id. - Aggregation gate evaluated: if
identity_status == 'Approved'ANDinstitution_approval_status == 'Approved'→ Flow 3D triggered via internal webhook. - If any status is still
'Pending', Zap terminates and waits.
5. Basic Flow
Sub-flow A — Dots Payee Creation (inside Process Veriff Handoff)
- Veriff webhook arrives at the backend
Process Veriff Handoffendpoint. - Backend validates Veriff cryptographic signature (HMAC).
- Backend extracts from the Veriff payload:
user_id,verification_status,legal_name,address.- 3a. If
verification_status != 'approved'→ update Users table status and halt (handled in UC_5.2). - 3b. If
verification_status == 'approved'→ continue.
- 3a. If
- Backend queries Users table:
SELECT dots_payee_id FROM Users WHERE user_id = extracted_user_id.- 4a. If
dots_payee_id IS NOT NULL(second cycle) → skip to Step 8 (second-cycle path). See Alternative Flow. - 4b. If
dots_payee_id IS NULL→ proceed to Step 5.
- 4a. If
POST /v2/users— create Dots user with Veriff-extractedlegal_name+ SIM contact fields.- Payload:
first_name+last_namefrom Verifflegal_name(split into parts),email,country_code,phone_number,metadata.internal_id=user_id. Must use Veriff legal name — NOT SIM registration name — because Dots IRS TIN matching runs against stored profile name, not W-9 payload. Known Dots bug (fix in progress as of 2026-08-25). - On success: store returned Dots user ID as
dots_payee_idin Users table. - On failure (non-200 / timeout): Exponential Backoff 8× retry via BullMQ (STAGE3-085). On exhaustion → Dead Letter Queue + SEV1 Slack alert.
identity_statusNOT updated. (Source: STAGE3-052 / H-04, STAGE3-085 confirmed 2026-08-15; legal_name correction: CR-20260825-001)
- Payload:
PUT /v2/users/{dots_payee_id}/addresses— pre-fill Veriff-extracted address on Dots profile.- Sends normalized address JSON (line_1/line_2/city/state/postcode/country) from Veriff payload. No TIN, DOB, or signature required.
- This populates the address field on W-8BEN/W-9 form in Dots Flow UI — trader sees it pre-filled.
PUT /v2/users/{id}/complianceis NOT called from middleware in this flow: that endpoint signs and finalizes the form immediately. Only invoke if middleware has all required fields (TIN for W-9; DOB + signature for W-8BEN). With current design, trader self-enters TIN/signs.- If
400 addressinvalid→ skip address pre-fill, continue. Trader self-enters address on Dots Flow UI. Non-blocking. (Source: CR-20260825-001 2026-08-25)
POST /v2/flows(manage-payouts step) — generate personalizedflow_link.- Call Dots API
POST /v2/flows. - Receive
flow_link— personalized, session-scoped URL with pre-filled tax form. - Store
flow_linkin Users table.
- Call Dots API
- Update KYC status.
-- First-cycle (dots_payee_id was NULL — arrived here via 4b): UPDATE Users SET identity_status = 'Approved', institution_approval_status = 'Approved' WHERE user_id = extracted_user_id -- Second-cycle (dots_payee_id was NOT NULL — arrived here via 4a, H-07/STAGE3-055): UPDATE Users SET identity_status = 'Approved', institution_approval_status = 'Approved', payout_status = 'Approved' WHERE user_id = extracted_user_id - Dispatch "Payout Profile Setup" email (first cycle only).
- Backend fires internal webhook to Zapier.
- Zapier sends email via AWS SES containing
flow_link. - Second cycle: Step 9 is skipped (
payout_statusalready set at Step 8).
Sub-flow B — Payout Verification Handler (Flow 3C)
-
Dots sends
user.updatedwebhook to Zapier/middleware, containinguser_id. -
Middleware immediately calls
GET /v2/users/{dots_payee_id}to re-fetch current state. Do NOT parse compliance fields directly from webhook payload — Dots does not guarantee all 5 fields are present in the payload. (Source: CR-20260825-001 2026-08-25) -
Validate 5-field health check on GET response:
Field Required value status"verified"default_payout_methodnon-null compliance.must_collect_1099falsecompliance.w8_ben_collectedtrueorw8_ben_skippedcompliance.flaggedfalse- All 5 pass → proceed to Step 4.
compliance.flagged = true→ blockpayout_statusupdate; SEV-1 alert → Ops; Ops manual override (reason + evidence + audit log). If form data deeply mismatched → Dots support must reset form by hand. See §7 Exceptional Flow.- Any other field fails → Zap terminates; waits for next
user.updatedevent.
-
Zapier UPDATE Users table:
payout_status = 'Approved'WHEREuser_id = webhook.user_id. -
Aggregation gate check: Zapier queries Users table for
user_id:- IF
identity_status == 'Approved'ANDinstitution_approval_status == 'Approved'→ fire internal webhook to trigger Flow 3D (UC_5.5). - ELSE → Zap terminates; waits for remaining approvals (identity or institution still
'Pending').
- IF
6. Alternative Flow
-
[Sub-flow A — Second cycle:
dots_payee_id IS NOT NULLat Step 4a (H-07/STAGE3-055)]- Backend detects
dots_payee_id IS NOT NULL. Skips steps 5–7 (Dots API calls). - Step 8 second-cycle path: sets
identity_status = 'Approved',institution_approval_status = 'Approved',payout_status = 'Approved'all in one DB write. - Step 9 (email) is skipped. No "Payout Profile Setup" email dispatched.
- Aggregation gate fires immediately after Step 8 if all conditions met.
- Rationale (confirmed): Dots does NOT re-issue an Active/Payable webhook for existing payee accounts.
payout_statusmust be set directly by Middleware. (Source: STAGE3-055 / H-07 confirmed 2026-08-15)
- Backend detects
-
[Sub-flow B — Aggregation gate not yet met when payout is approved]
payout_statusis set to'Approved'but one or both ofidentity_statusorinstitution_approval_statusare still'Pending'.- Flow 3C Zap terminates. No Flow 3D trigger yet.
- When Flow 3B (Veriff — now covers ALL traders per STAGE3-037 [CHR-46]) later sets the remaining approval fields, the gate is re-evaluated at that time.
Flow 3B.2 (Ironbeam) deprecated (STAGE3-039).
7. Exceptional Flow
-
[Sub-flow A — Dots API failure (Step 5
POST /v2/users, Step 6 Submit Compliance, or Step 7POST /v2/flows)]- Non-200 or connection timeout at any of the 3 Dots steps.
- Retry: Exponential Backoff 8× via BullMQ/Redis (+5s, +15s, +1m, +5m, +15m, +1h, +3h, +12h). (Source: STAGE3-085 / Kịch bản 4 confirmed 2026-08-15)
- On exhaustion: Dead Letter Queue + SEV1 Slack alert #ops-compliance → Ops intervenes via Ops Console.
dots_payee_idremains NULL (if failed at Step 5).identity_statusNOT updated. Trader locked at aggregation gate.- Special case — HTTP 200 but no
payee_idreturned: Validation Gate blocks NULL write todots_payee_id, enqueues retry. (Source: STAGE3-069 / M-10 confirmed 2026-08-15)
-
[Sub-flow A — Dots profile: W-9/W-8BEN Rejected or TIN/SSN mismatch (Kịch bản 1 / STAGE3-082)]
- Trader completes flow link but Dots Compliance rejects the submission.
- Middleware receives Dots webhook → sets/keeps
payout_status = 'Pending'→ callsPOST /v2/flowsto generate New Session Flow Link (old link invalidated after first submit). - AWS SES dispatches email
Dots_Profile_Action_Needed(orLevel_6_International_Contractor_Dots_Profile_Action_Needed) with new link.
-
[Sub-flow A — Bank linking failure via Plaid (Kịch bản 2 / STAGE3-083)]
- Trader completes tax form but fails bank link. Dots marks flow as Completed but account is Not Payable. No new flow link needed.
- Dashboard renders "Manage Payouts" button linking to static
payout_portal_urlfromGET /current-level-detail. Trader self-heals by re-linking bank via phone + OTP.
-
[Sub-flow B — Dots webhook missing
metadata.internal_id(Kịch bản 3 / STAGE3-084)]- Middleware cannot correlate webhook to a
user_id. Performs fallback query by email/phone. If still no match → SEV1 Slack alert #ops-compliance + ZendeskCompliance_Reviewticket for manual assignment.
- Middleware cannot correlate webhook to a
-
[Sub-flow B — Dots webhook not received (trader never completes Dots setup — STAGE3-068 / M-09)]
payout_statusstays'Pending'indefinitely. No automated reminder email.flow_linkhas TTL set by Dots.- Aggregation gate holds. Trader blocked from Flow 3D.
-
[Sub-flow B — Dots profile becomes Suspended, Paused, or Failed after initial approval]
Confirmed — STAGE3-038 [CHR-44] 2026-08-12: This does NOT happen automatically without building a dedicated listener. Current architecture only listens for the
Active and Payablesuccess webhook. To handle suspension events:- New webhook listener required: Create a webhook listener for any Dots status change to
'Suspended','Paused', or'Failed'. - DB update: When the suspension webhook fires → immediately execute:
UPDATE Users SET payout_status = 'Suspended' WHERE user_id = webhook.user_id - Flow 3D blocked automatically: Because Flow 3D requires
payout_status = 'Approved', setting it to'Suspended'is sufficient to break the Flow 3D chain. No additional gate check change needed in Flow 3D. - Flow 3H pre-condition gap (critical): If a trader's Dots account is suspended AFTER contract signing but BEFORE market data setup, Flow 3H would incorrectly fund them because it currently only checks
contract_statusandsetup_status.payout_status == 'Approved'must be added as a mandatory pre-condition check to Flow 3H (UC_5.8). See BR_5.4.8. - Trader notification: Automatically dispatch
Dots_Profile_Action_Neededemail to the trader so they know they need to fix their tax or routing information before they can proceed. See BR_5.4.9.
(Source: Client confirmed STAGE3-038 [CHR-44] 2026-08-12; zapier_v7_full.txt line 728 —
Dots_Profile_Action_Neededemail referenced in Stage 5/6) - New webhook listener required: Create a webhook listener for any Dots status change to
8. Business Rules
<a id="BR_5.4.1"></a>
BR_5.4.1: Auto-Create from Veriff — No Trader Re-entry
The Dots payee profile is created automatically by the backend using legal_name and address extracted directly from the Veriff KYC payload. The trader is NOT required to manually re-enter their legal name or address in the Dots form. This eliminates a data-entry step and reduces name mismatch risk.
(Source: RFQ_ Stack Trading Prop Tech V7.pdf §Process Veriff Handoff, lines 766–769)
<a id="BR_5.4.2"></a>
BR_5.4.2: Idempotent Payee Creation — Skip if Profile Exists
If the Users table already has a non-NULL dots_payee_id for the user_id at the time the Veriff handoff runs, the backend does NOT call POST /payees again. It updates local KYC status to 'Approved' and exits the creation path. This prevents duplicate Dots profiles for traders who have been through a prior account cycle.
(Source: RFQ_ Stack Trading Prop Tech V7.pdf §Process Veriff Handoff, lines 762–765)
<a id="BR_5.4.3"></a>
BR_5.4.3: Tax Form Type Determined by Billing Country
The Dots white-labeled onboarding link natively presents the appropriate tax form based on the trader's Billing_Country:
- US traders (
Billing_Country = 'US'): W-9 form. - International traders (all other countries): W-8BEN form.
The form type selection is handled natively by the Dots platform — Stack Trading does not render the tax form itself.
(Source: Zapier Integration V7.pdf Flow 3A lines 1070–1073; RFQ_ Stack Trading Prop Tech V7.pdf lines 780–782)
<a id="BR_5.4.4"></a>
BR_5.4.4: Payout Profile Setup Email Contains Dots Hosted Link
After dots_payee_id is stored, the backend fires a webhook to Zapier, which triggers the "Payout Profile Setup" email to the trader via AWS SES. This email contains the Dots white-labeled link that:
- Collects the W-9 or W-8BEN tax form (per BR_5.4.3).
- Collects the trader's payout routing information (bank account, debit card, etc.).
The Dots platform handles all tax form collection and payout routing setup — Stack Trading does not collect this data directly.
(Source: RFQ_ Stack Trading Prop Tech V7.pdf §Process Veriff Handoff, lines 778–782)
<a id="BR_5.4.5"></a>
BR_5.4.5: Flow 3C Trigger — user.updated Webhook + 5-Field Health Check (Updated CR-20260825-001)
payout_status is only set to 'Approved' when ALL 5 conditions pass after re-fetching GET /v2/users/{dots_payee_id} on receipt of a user.updated webhook from Dots:
status = "verified"default_payout_methodis non-nullcompliance.must_collect_1099 = falsecompliance.w8_ben_collected = trueorw8_ben_skippedcompliance.flagged = false
The webhook payload must NOT be parsed directly for compliance fields — Dots does not guarantee all fields are present in the payload. The re-fetch pattern (user.updated → GET /v2/users/{id} → validate) is the confirmed Dots-recommended approach.
Partial completion (e.g., tax form signed but no payout account linked) does NOT pass all 5 conditions and does NOT set payout_status = 'Approved'.
(Source: CR-20260825-001 — Dots vendor confirmed 2026-08-25; supersedes "Active and Payable" webhook description from Zapier Integration V7.pdf Flow 3C lines 1158–1161)
<a id="BR_5.4.6"></a>
BR_5.4.6: Aggregation Gate — Two-Field Check in Flow 3C
Flow 3C's aggregation gate checks identity_status == 'Approved' AND institution_approval_status == 'Approved' before triggering Flow 3D. This is intentionally a two-field check (not three) because payout_status is the field being set by this flow — it is already guaranteed to be 'Approved' at this point.
Cross-reference: Flow 3B (UC_5.2) and Flow 3B.2 (UC_5.3) each check all three fields (including UPDATED (STAGE3-037 [CHR-46]/039 [CHR-46] — [CHR-46] — 2026-08-12): Flow 3B.2 / UC_5.3 deprecated. Flow 3B (UC_5.2) now handles ALL traders (Futures and Forex). Whichever of Flow 3B (UC_5.2) or Flow 3C (UC_5.4) fires last will trigger Flow 3D.payout_status). Whichever flow last sets its field to 'Approved' will be the one that successfully triggers Flow 3D.
(Source: Zapier Integration V7.pdf Flow 3C lines 1169–1175)
<a id="BR_5.4.7"></a>
BR_5.4.7: Veriff HMAC Signature Validation — Mandatory Security Gate
The Process Veriff Handoff backend endpoint MUST validate the Veriff cryptographic signature (HMAC) before processing any payload content. If validation fails, the request is rejected and no KYC status update or Dots API call occurs.
(Source: RFQ_ Stack Trading Prop Tech V7.pdf §Process Veriff Handoff, line 754)
🔄 CR — STAGE3-038 [CHR-44]: Dots suspension webhook listener added. Sets payout_status = 'Suspended' on Dots Suspended/Paused/Failed events. payout_status == 'Approved' added as mandatory pre-condition to Flow 3H.
<a id="BR_5.4.8"></a>
BR_5.4.8: Dots Suspension Webhook Listener — payout_status = 'Suspended' (STAGE3-038 [CHR-44] 2026-08-12)
The system MUST implement a webhook listener for Dots status change events. When Dots sends a webhook indicating the payee profile status has changed to 'Suspended', 'Paused', or 'Failed':
- Backend updates
payout_status = 'Suspended'in the PostgreSQL Users table. - This DB update is sufficient to break the Flow 3D chain (Flow 3D requires
payout_status = 'Approved'). - No separate gate change is required in Flow 3D — the existing check on
payout_status == 'Approved'will block the trigger.
Critical gap in Flow 3H: Flow 3H currently only checks contract_status and setup_status. If a trader's Dots account is suspended after contract signing but before market data setup, Flow 3H would fund them incorrectly. payout_status == 'Approved' MUST be added as a pre-condition check to Flow 3H (UC_5.8). See UC_5.8 §3 Pre-conditions.
(Source: Client confirmed STAGE3-038 [CHR-44] 2026-08-12)
🔄 CR — STAGE3-038 [CHR-44]: Dots_Profile_Action_Needed email dispatch added on suspension. Non-blocking relative to DB update.
<a id="BR_5.4.9"></a>
BR_5.4.9: Dots_Profile_Action_Needed Email on Suspension (STAGE3-038 [CHR-44] 2026-08-12)
When the Dots suspension webhook fires (triggering payout_status = 'Suspended'), the system MUST automatically dispatch the Dots_Profile_Action_Needed email to the trader. This email informs the trader that their tax or routing information needs to be corrected before they can proceed with live trading onboarding.
The email dispatch is non-blocking relative to the DB update — both must execute, but email failure must not roll back the payout_status = 'Suspended' write.
(Source: Client confirmed STAGE3-038 [CHR-44] 2026-08-12; zapier_v7_full.txt line 728 — Dots_Profile_Action_Needed referenced)
9. Wireframe / UI
No screen is required for this UC. Both sub-flows are fully automated backend and Zapier processes. The only trader-facing touchpoint is the Dots white-labeled hosted link (owned and rendered by Dots, not by Stack Trading) and the "Payout Profile Setup" email (sent by Zapier/AWS SES).
10. Screen Description and Business Rules
N/A — this use case contains no Stack Trading-owned UI screens. All processing is automated via the backend Process Veriff Handoff endpoint, Dots API, Zapier, and AWS SES.
END OF UC_5.4
Update History
| Date | Version | Section | Change From | Change To | Source |
|---|---|---|---|---|---|
| 2026-08-11 | v1 → v1.1 | §5 Sub-flow A Steps 4–8 — execution order | identity_status = 'Approved' written at Step 4a exit / after Step 4a-b split; Dots call at Step 5; no explicit gate note | Dots call at Step 5 (with failure halt note);dots_payee_id saved at Step 6; identity_status = 'Approved' written at Step 7 AFTER save; explicit note: identity_status gated on dots_payee_id success | STAGE3-025 confirmed 2026-08-11 |
| 2026-08-11 | v1 → v1.1 | §7 Exceptional Flow — POST /payees error | [MISSING] — behavior undefined | Confirmed: halt on failure; identity_status stays 'Pending' (never written); no auto-retry; Break-Glass Runbook (POST /api/bps/kyc/reset or Ops Console manual override) | STAGE3-025 confirmed 2026-08-11 |
| 2026-08-11 | v1 → v1.1 | §7 Exceptional Flow — empty payee_id | [MISSING] | Same halt + Break-Glass path as POST /payees non-200 | STAGE3-025 confirmed 2026-08-11 |
| 2026-08-11 | v1 → v1.1 | §6 Alternative Flow — existing profile (Step 4a) | "exits at step 3" (stale step number reference) | Updated to "exits at Step 4a" matching renumbered flow | Step renumbering in this update |
| 2026-08-22 | v1.6 → v1.7 | All sections — CHR tag standardization | Bare STAGE3 codes without CHR tags; date-based CR refs | B8: STAGE3-037 → STAGE3-037 [CHR-46] (8 occurrences). B9: STAGE3-038 → STAGE3-038 [CHR-44] (8 occurrences). A36: CR-20260813-001 → [CHR-46] (2 occurrences). B10: STAGE3-039 → STAGE3-039 [CHR-46] (1 occurrence). | CHR_Tag_Change_Plan_20260822_v4.md |
| 2026-08-25 | v1.7 → v1.8 | §1 Description; §2 Sub-flow B trigger; §5 Sub-flow A Step 5/6; §5 Sub-flow B Steps 1–5; §8 BR_5.4.5 | POST /v2/users used SIM first_name/last_name; Step 6 = "Submit Compliance Information"; Sub-flow B trigger = "Active and Payable" webhook; BR_5.4.5 based on Active/Payable | POST /v2/users must use Veriff legal_name (IRS TIN matching runs on stored profile name — Dots bug in progress); Step 6 = PUT /v2/users/{id}/addresses (pre-fill only, not compliance submission); Sub-flow B trigger = user.updated → GET /v2/users/{id} re-fetch → 5-field health check; BR_5.4.5 updated to 5-field check pattern | CR-20260825-001 (Dots vendor 2026-08-25) |