StackTrading Docs

SRS: UC_9.14 — Flow 32: Velocity Reward Engine

FieldValue
UC_IDUC_9.14
Versionv1.1
Last Updated2026-11-05
BA PiClinh.nguyen34
CategorySTAGE 9: GROWTH & REFERRAL
ModuleReferral Loyalty Loop
FunctionFlow 32 — Velocity Reward Engine
Document ReferencesRFQ_ Stack Trading Prop Tech V7.pdf (§Velocity Reward Engine) · Zapier Integration V7.pdf (§Flow 32)

1. UC Index

UC_IDFunctionDescription
UC_9.14Flow 32 — Velocity Reward EngineIssues 100%-off EVAL_L1 promo codes at referral milestones (3 and 6 successful referrals). Triggered by Everflow S2S webhook (EV_MILESTONE_3_REFS / EV_MILESTONE_6_REFS). Executes 4-step pipeline: idempotency gate → sanctions check → promo code generation → Klaviyo email → Discord broadcast. CFTC/NFA-compliant audit trail.

UC_9.14 — Flow 32: Velocity Reward Engine

FieldValue
Use CaseVelocity Reward Engine
DescriptionAt referral milestones of 3 or 6 successful referrals, Everflow fires an S2S webhook (EV_MILESTONE_3_REFS or EV_MILESTONE_6_REFS). Middleware executes: (1) idempotency gate via PostgreSQL SELECT ... FOR UPDATE + UNIQUE index on provider_event_id, (2) sanctions screening against Compliance_geo_restrictions, (3) promo code generation (EVAL_L1, 100% discount) inserted into promo_codes table, (4) Klaviyo Velocity_Reward_Unlocked email, (5) Discord broadcast to #trading-floor-announcements via Redis queue with 5 msg/5 s rate cap. Audit written to bps_audit_logs and replicated to S3 Glacier Object Lock (WORM) for CFTC/NFA 5-year retention.
Zapier FlowFlow 32 (Velocity Reward Engine)
Trigger SourceEverflow S2S Webhook
3rd PartyEverflow · Klaviyo · Discord Bot API
Middleware EndpointPOST /api/referral/velocity-reward
ReleaseRelease 2 (QnA_BACKGROUND_MECHANISMS_CRON.md [BG-012] — client sheet 2026-11-04)

2. Trigger

Event: Everflow S2S webhook received by Middleware at POST /api/referral/velocity-reward.

Event NameMilestoneMeaning
EV_MILESTONE_3_REFS3 successful referralsReferrer reaches 3-referral velocity tier
EV_MILESTONE_6_REFS6 successful referralsReferrer reaches 6-referral velocity tier

Everflow fires the webhook when the referral count for origin_user_id increments past the milestone threshold. Middleware is the sole entry point — the flow does not pass through Zapier.

(Source: Zapier Integration V7.pdf §Flow 32)


3. Pre-conditions

IDPre-condition
P1Everflow S2S webhook received with valid provider_event_id, origin_user_id, and event_type (EV_MILESTONE_3_REFS or EV_MILESTONE_6_REFS)
P2provider_event_id has not previously been processed (idempotency gate not yet tripped)
P3origin_user_id resolves to a known user in the system
P4billing_country / billing_region of origin_user_id is not present in Compliance_geo_restrictions (sanctions clear)

4. Post-conditions

#Post-condition
1Idempotency lock record written: provider_event_id marked as processed in idempotency table
2Promo code record inserted into promo_codes table: applicable_product_id = 'EVAL_L1', discount_percent = 100, is_used = false, origin_user_id set
3Klaviyo Velocity_Reward_Unlocked transactional email dispatched to origin_user_id containing promo code
4Discord message broadcast to #trading-floor-announcements via Redis queue
5Audit entry written to bps_audit_logs
6Audit entry replicated to S3 Glacier Object Lock (WORM) — 5-year + 1-month retention

5. Basic Flow

Step 1 — Idempotency Gate

Middleware acquires a row-level lock before any write:

BEGIN;
SELECT id FROM idempotency_log
WHERE provider_event_id = :provider_event_id
FOR UPDATE;
  • If row exists: return HTTP 200 OK with { "status": "duplicate", "skipped": true } — do not proceed.
  • If row does not exist: insert new row with provider_event_id, origin_user_id, event_type, received_at; hold lock through commit at Step 3.

The UNIQUE index on provider_event_id provides a hard backstop against concurrent inserts.

(Source: RFQ_ Stack Trading Prop Tech V7.pdf §Velocity Reward Engine)

Step 2 — Sanctions Gate

SELECT 1 FROM Compliance_geo_restrictions
WHERE country_code = :billing_country
  AND (region_code = :billing_region OR region_code IS NULL);
  • If row found: return HTTP 403 Forbidden with { "error": "SANCTIONS_BLOCKED", "user_id": :origin_user_id }. Abort flow. Write sanctions-block event to bps_audit_logs.
  • If row not found: proceed to Step 3.

(Source: RFQ_ Stack Trading Prop Tech V7.pdf §Velocity Reward Engine)

Step 3 — Promo Code Generation

INSERT INTO promo_codes (
  code,
  applicable_product_id,
  discount_percent,
  is_used,
  origin_user_id,
  event_type,
  created_at
) VALUES (
  :generated_code,        -- cryptographically random alphanumeric, 16 chars
  'EVAL_L1',
  100,
  false,
  :origin_user_id,
  :event_type,
  NOW()
);
COMMIT;  -- releases FOR UPDATE lock from Step 1

generated_code is a 16-character cryptographically random alphanumeric string, unique by UNIQUE constraint on code column.

(Source: RFQ_ Stack Trading Prop Tech V7.pdf §Velocity Reward Engine)

Step 4 — Klaviyo Email

Middleware calls Klaviyo Transactional API:

  • Template: Velocity_Reward_Unlocked
  • To: origin_user_id email address
  • Payload fields: promo_code, event_type, milestone_count (3 or 6), applicable_product (EVAL_L1)

On Klaviyo API failure: apply exponential backoff retry (see Exc-1). Do not block Discord dispatch if Klaviyo retries are in progress.

(Source: Zapier Integration V7.pdf §Flow 32)

Step 5 — Discord Broadcast

Enqueue Discord message to Redis queue for #trading-floor-announcements:

  • Rate limit: 5 messages per 5 seconds (enforced by queue consumer).
  • Implementation: native fetch() only — axios is explicitly prohibited.
  • Message content: Announce milestone achievement for origin_user_id (display name or anonymized handle per community policy).

Queue consumer dequeues and calls Discord Bot API within rate limit window.

(Source: Zapier Integration V7.pdf §Flow 32)

Step 6 — Audit Log

Write to bps_audit_logs:

{
  "event_type": "VELOCITY_REWARD_ISSUED",
  "origin_user_id": "<id>",
  "provider_event_id": "<id>",
  "milestone": 3,
  "promo_code": "<code>",
  "timestamp": "<ISO-8601>"
}

Replicate to S3 Glacier Object Lock (WORM). Retention: 5 years + 1 month. First 2 years stored in immediately accessible tier. After 2 years: Glacier Deep Archive. Per CFTC/NFA record-keeping requirements.

(Source: RFQ_ Stack Trading Prop Tech V7.pdf §Velocity Reward Engine)


6. Alternative Flows

Alt-1 — Duplicate event (provider_event_id already processed)

  • Idempotency gate detects existing row (Step 1).
  • Return HTTP 200 OK: { "status": "duplicate", "skipped": true }.
  • No promo code generated. No email. No Discord. No audit event (event already logged at first processing).
  • Flow ends cleanly.

7. Exceptional Flows

Exc-1 — Klaviyo API failure (Step 4)

Middleware applies exponential backoff:

delay(attempt) = 5s × 2^attempt
  attempt 1 → 10s
  attempt 2 → 20s
  attempt 3 → 40s

After 3 failed retries (total backoff window ~70s):

  • Log WARN entry in bps_audit_logs: { "event": "KLAVIYO_RETRY_EXHAUSTED", "promo_code": "<code>", "origin_user_id": "<id>" }.
  • Send SEV-2 Slack alert to #dev_ops: "⚠️ [SEV-2] Velocity Reward email failed after 3 retries for user <id>. Promo code <code> was issued but email not delivered. Manual resend required."
  • Discord broadcast (Step 5) proceeds regardless of Klaviyo failure — promo code was already committed.

(Source: RFQ_ Stack Trading Prop Tech V7.pdf §Velocity Reward Engine)

Exc-2 — Discord API failure (Step 5)

Redis queue consumer retries per Discord Bot rate-limit guidance. If Discord channel is unavailable (non-2xx after retries):

  • Log WARN in bps_audit_logs.
  • Slack alert to #dev_ops: "⚠️ [SEV-2] Discord broadcast failed for Velocity Reward event <provider_event_id>.".
  • Non-blocking — promo code and email are unaffected.

Exc-3 — Sanctions block (Step 2)

  • Return HTTP 403 Forbidden.
  • Write sanctions-block record to bps_audit_logs with event_type = 'VELOCITY_REWARD_SANCTIONS_BLOCKED'.
  • No promo code generated. No email. No Discord.
  • S3 Glacier replication of the block event still applies (CFTC/NFA audit trail).

Exc-4 — promo_codes INSERT collision (UNIQUE constraint on code)

  • Middleware regenerates a new random code and retries INSERT (max 3 attempts).
  • If all 3 retries fail: return HTTP 500, log ERROR, SEV-2 Slack alert to #dev_ops.
  • Probability of collision with 16-char random alphanumeric is negligible but the guard must exist.

8. Business Rules

BR_9.14.1: Idempotency Is Mandatory — PostgreSQL FOR UPDATE + UNIQUE Index

Every incoming Everflow webhook MUST be checked for prior processing using SELECT ... FOR UPDATE on the idempotency table before any write. A UNIQUE constraint on provider_event_id provides the hard backstop. Duplicate events MUST return HTTP 200 OK silently — not HTTP 4xx — to prevent Everflow retry storms.

(Source: RFQ_ Stack Trading Prop Tech V7.pdf §Velocity Reward Engine)

BR_9.14.2: Sanctions Gate Executes Before Promo Code Generation

The Compliance_geo_restrictions check on billing_country/billing_region MUST run before any promo code is written to promo_codes. A sanctioned user must never receive a promo code or email, even if the Everflow milestone event is legitimate.

(Source: RFQ_ Stack Trading Prop Tech V7.pdf §Velocity Reward Engine)

BR_9.14.3: Promo Code Parameters Are Fixed

Every promo code issued by Flow 32 MUST have:

  • applicable_product_id = 'EVAL_L1'
  • discount_percent = 100
  • is_used = false (initial state)

No other product or discount value is valid for this flow.

(Source: RFQ_ Stack Trading Prop Tech V7.pdf §Velocity Reward Engine)

BR_9.14.4: Discord Implementation — native fetch() Only, No axios

All Discord API calls within Flow 32 MUST use the native fetch() API. axios is explicitly prohibited. This applies to all Discord Bot calls made from Middleware within this flow.

(Source: Zapier Integration V7.pdf §Flow 32)

BR_9.14.5: Discord Rate Limit — 5 Messages per 5 Seconds via Redis Queue

Discord broadcasts MUST be enqueued through Redis and consumed at a maximum rate of 5 messages per 5 seconds. Direct synchronous Discord calls that bypass the queue are prohibited to prevent API rate-limit bans.

(Source: Zapier Integration V7.pdf §Flow 32)

BR_9.14.6: CFTC/NFA Audit Trail — S3 Glacier WORM, 5-Year + 1-Month Retention

All audit events (reward issuance, sanctions blocks, retry exhaustion) MUST be written to bps_audit_logs and replicated to S3 Glacier Object Lock (WORM). Retention: 5 years + 1 month. First 2 years in immediately accessible tier. After 2 years: Glacier Deep Archive. Manual deletion is prohibited by Object Lock policy.

(Source: RFQ_ Stack Trading Prop Tech V7.pdf §Velocity Reward Engine)

BR_9.14.7: Exponential Backoff — Base 5s, 3 Retries, SEV-2 on Exhaustion

Third-party API failures (Klaviyo, Discord) MUST apply exponential backoff: delay = 5s × 2^attempt (10s, 20s, 40s). After 3 failed retries, dispatch SEV-2 Slack alert to #dev_ops. Flow does not crash — downstream steps that have already completed are not rolled back.

(Source: RFQ_ Stack Trading Prop Tech V7.pdf §Velocity Reward Engine)

BR_9.14.8: Two Eligible Milestone Events Only

Only EV_MILESTONE_3_REFS and EV_MILESTONE_6_REFS are valid triggers for Flow 32. Any other event_type value received at POST /api/referral/velocity-reward MUST return HTTP 400 Bad Request and be logged as INVALID_EVENT_TYPE. Each milestone (3 and 6) issues exactly one single-use 100% EVAL_L1 code.

(Source: Zapier Integration V7.pdf §Flow 32; QnA_STAGE1_CHECKOUT_ONBOARDING.md STAGE1-064; UC_9.x_Client_Questions.md F32-01 — milestones 3/6 confirmed 2026-11-05)


9. Acceptance Criteria

AC_IDFlowGivenThenType
AC-9.14-01Happy path — 3-referral milestoneValid EV_MILESTONE_3_REFS webhook, sanctions clear, first occurrencePromo code inserted (EVAL_L1, 100%); Velocity_Reward_Unlocked email sent; Discord broadcast queued; audit log written; HTTP 200 OK returnedIntegration
AC-9.14-02Happy path — 6-referral milestoneValid EV_MILESTONE_6_REFS webhook, sanctions clear, first occurrenceSame as AC-9.14-01; event_type = 'EV_MILESTONE_6_REFS' in promo_codes recordIntegration
AC-9.14-03Idempotency — duplicate eventSame provider_event_id received twiceSecond call returns HTTP 200 { "status": "duplicate", "skipped": true }; no second promo code; no second emailIntegration
AC-9.14-04Concurrent duplicateTwo simultaneous requests with same provider_event_idExactly one promo code created; second transaction blocked by SELECT ... FOR UPDATE + UNIQUE constraintIntegration
AC-9.14-05Sanctions blockUser's billing_country matches Compliance_geo_restrictionsHTTP 403 returned; no promo code; no email; sanctions-block event in bps_audit_logsIntegration
AC-9.14-06Klaviyo retry exhaustionKlaviyo returns non-2xx for all 3 retry attemptsSEV-2 Slack alert to #dev_ops; promo code already committed remains valid; Discord broadcast still dispatchedIntegration
AC-9.14-07Discord rate limit10 reward events arrive within 1 secondRedis queue consumers dispatch ≤ 5 messages per 5 s; no HTTP 429 from DiscordIntegration
AC-9.14-08Discord uses native fetchDiscord call in Flow 32 implementationNo axios import present in the request pathCode review
AC-9.14-09Invalid event_typeWebhook with event_type = 'EV_UNKNOWN'HTTP 400 Bad Request; INVALID_EVENT_TYPE logged; no promo code createdIntegration
AC-9.14-10Audit WORMReward event processed successfullybps_audit_logs row present; S3 Glacier Object Lock replication confirmed; Object Lock mode = COMPLIANCEIntegration

10. Data Model

Table: promo_codes

ColumnTypeConstraintsDescription
idBIGSERIALPKAuto-increment primary key
codeVARCHAR(32)UNIQUE NOT NULL16-char cryptographically random alphanumeric
applicable_product_idVARCHAR(64)NOT NULLFixed: 'EVAL_L1' for Flow 32
discount_percentSMALLINTNOT NULLFixed: 100 for Flow 32
is_usedBOOLEANNOT NULL DEFAULT falseWhether code has been redeemed
origin_user_idBIGINTFK → users.idReferrer who earned the reward
event_typeVARCHAR(64)NOT NULL'EV_MILESTONE_3_REFS' or 'EV_MILESTONE_6_REFS'
created_atTIMESTAMPTZNOT NULL DEFAULT NOW()Code issuance timestamp
used_atTIMESTAMPTZNULLABLETimestamp of redemption

Table: idempotency_log (logical — may be same as existing idempotency table)

ColumnTypeConstraintsDescription
idBIGSERIALPK—
provider_event_idVARCHAR(128)UNIQUE NOT NULLEverflow event ID — idempotency key
origin_user_idBIGINTNOT NULL—
event_typeVARCHAR(64)NOT NULL—
received_atTIMESTAMPTZNOT NULL DEFAULT NOW()—

11. API Reference

POST /api/referral/velocity-reward

FieldValue
MethodPOST
AuthEverflow webhook HMAC signature (header: X-Everflow-Signature)
CallerEverflow S2S webhook
Content-Typeapplication/json

Request payload:

{
  "provider_event_id": "ef_evt_abc123xyz",
  "origin_user_id": 10042,
  "event_type": "EV_MILESTONE_3_REFS",
  "referral_count": 3,
  "billing_country": "US",
  "billing_region": "TX"
}

Response — Happy path (HTTP 200 OK):

{
  "status": "success",
  "promo_code": "ABCD1234EFGH5678",
  "applicable_product": "EVAL_L1",
  "discount_percent": 100,
  "email_dispatched": true,
  "discord_queued": true
}

Response — Duplicate event (HTTP 200 OK):

{
  "status": "duplicate",
  "skipped": true
}

Response — Sanctions block (HTTP 403 Forbidden):

{
  "error": "SANCTIONS_BLOCKED",
  "user_id": 10042
}

Response — Invalid event_type (HTTP 400 Bad Request):

{
  "error": "INVALID_EVENT_TYPE",
  "received": "EV_UNKNOWN",
  "accepted": ["EV_MILESTONE_3_REFS", "EV_MILESTONE_6_REFS"]
}
Request FieldTypeRequiredDescription
provider_event_idSTRINGYesEverflow's unique event ID — idempotency key
origin_user_idINTYesReferrer user ID
event_typeSTRINGYesEV_MILESTONE_3_REFS or EV_MILESTONE_6_REFS
referral_countINTYesCurrent referral milestone count (3 or 6)
billing_countrySTRINGYesISO 3166-1 alpha-2 country code for sanctions check
billing_regionSTRINGNoISO 3166-2 region/state code for sanctions check

(Source: RFQ_ Stack Trading Prop Tech V7.pdf §Velocity Reward Engine)


12. Open Questions

IDPriorityQuestionAssumption
Q1MShould the Discord broadcast include the user's display name, a pseudonym, or remain fully anonymous?BA assumption: anonymized handle or first name only; confirm with client for community policy
Q2LIs idempotency_log a dedicated table for Flow 32 or the existing system-wide idempotency table?BA assumption: system-wide table, filtered by event_type prefix EV_
Q3MWhat is the Klaviyo template ID / slug for Velocity_Reward_Unlocked?Placeholder name used; confirm with Marketing/Klaviyo config
Q4LIs S3 Glacier replication synchronous (within the request) or async (background job)?BA assumption: async background job; audit log written synchronously, S3 replication queued

13. Changelog

DateVersionChangePreviousAfterSource
2026-11-05v1.1§1 Release row; BR_9.14.8 (one code per milestone + sources)Release not stated; milestone model 3/6 vs pinned 2/6 + bundle unresolved (F32-01)Release 2; milestones 3/6 confirmed, one EVAL_L1 code per milestone — bundle answer (F32-02) not applicableClient sheet 2026-11-04 [BG-012]; F32-01 closed 2026-11-05; STAGE1-064
2026-10-01v1.0Initial document creation—Full spec: 4-step pipeline, idempotency gate, sanctions check, promo code generation, Klaviyo email, Discord broadcast, CFTC/NFA audit trailRFQ_ Stack Trading Prop Tech V7.pdf §Velocity Reward Engine; Zapier Integration V7.pdf §Flow 32

On this page