Simulation Flows
These endpoints let tests trigger the same async collection and processing pipelines that run in production, but scoped to specific test users.
Simulations are the bridge between test setup (creating users via /qa/integration/custom-user) and assertions (calling service APIs directly).
Each endpoint sends messages to SQS queues for downstream Lambda consumption, directly invokes a Lambda function, or injects events into a Kinesis stream — closely mirroring what production schedulers do.
The POST /qa/test/event endpoint supports direct Kinesis injection for lower-level integration scenarios.
Subscription Simulations
Daily Collections (POST /qa/simulate/subscriptions/daily)
Simulates the nightly scheduled job that collects subscription payments. The endpoint accepts a list of user IDs, fetches each user’s subscription records from the Subscription Service, and routes them into one of three SQS queues based on their current status. The queues are then consumed by the production Subscription Service Lambda workers.
Async: Yes — SQS messages are sent and the endpoint returns immediately. The caller must poll or wait before asserting on downstream state.
Request body:
{
"user_ids": ["uuid-1", "uuid-2"]
}
Behavior by subscription status:
| Status | SQS Queue (env var) | Consumer |
|---|---|---|
|
|
Subscription Service scheduled-collections Lambda |
|
|
Subscription Service paused-collections Lambda |
|
|
Subscription Service retry-collections Lambda |
Eligibility rules:
-
SCHEDULEDandPAUSEDsubscriptions must have asubscription_datestrictly before the current time. -
ERRORsubscriptions are eligible for retry only if they fall within the last 30 days. -
Subscriptions that do not meet eligibility are silently skipped.
Flow:
Caller → POST /qa/simulate/subscriptions/daily
→ Fetch subscriptions for each user_id (Subscription Service)
→ Sort into buckets: SCHEDULED / PAUSED / ERROR
→ Filter by eligibility (date < now; ERROR within 30 days)
→ SQS: scheduled-queue / paused-queue / retry-queue
→ Subscription Service Lambda consumes each queue
Webhook Collection (POST /qa/simulate/subscriptions/webhook)
Simulates inbound payment processor webhook events that trigger subscription collection.
Instead of routing by status bucket, this endpoint creates a CloudWatchEvent payload per user and sends all of them to a single SQS webhook queue.
It is used to test the webhook-driven collection path independently from the daily scheduler path.
Async: Yes — SQS messages are sent and the endpoint returns immediately.
Request body:
{
"users": [
{ "user_id": "uuid-1", "amount": 9.99 },
{ "user_id": "uuid-2", "amount": 14.99 }
]
}
Eligibility: Each user must have at least one subscription in SCHEDULED or ERROR status that was created within the last 2 months.
Users that do not meet this requirement are rejected and an error is returned for those entries.
SQS target: SubscriptionCollectionsWebhookQueueURL
Subscription Notifier (POST /qa/simulate/subscriptions/notifier)
Simulates the three-day advance notification job that alerts users their subscription payment is upcoming.
The endpoint accepts a list of user IDs, fetches their subscriptions from the Subscription Service, and for each subscription in SCHEDULED status it constructs an fmsdk event with type three_day_notification (version v1) keyed by subscription_id.
All events are sent as a batch to the subscription notifier SQS queue.
Async: Yes — SQS batch message is sent and the endpoint returns immediately.
Request body:
{
"user_ids": ["uuid-1", "uuid-2"]
}
Eligibility: Only subscriptions with SCHEDULED status produce notification events.
Subscriptions in any other status are silently skipped.
SQS target: SubscriptionNotifierWorkerQueueURL
Use case: Test that users receive pre-payment notification emails/push alerts before the scheduled collection date.
Float Simulations
Daily Collections (POST /qa/simulate/floats/daily)
Simulates the daily float (cash advance) collection job.
The endpoint accepts a list of user IDs, calls the Float Service GetActiveFloats for each, filters floats by collectibility, and sends a FloatCollectionEvent per float to the daily collection SQS queue.
Async: Yes — SQS messages are sent and the endpoint returns immediately.
Request body:
{
"user_ids": ["uuid-1", "uuid-2"]
}
Process types and eligibility:
| Float Status | Eligible Condition | Process value sent in event |
|---|---|---|
|
Due today or earlier (not yet overdue) |
|
|
Always collectable regardless of date |
|
SQS target: FloatCollectionsDailyQueueURL
Each event payload is a FloatCollectionEvent containing the Process type, the Float record, and a Runtime timestamp.
Flow:
Caller → POST /qa/simulate/floats/daily
→ GetActiveFloats per user_id (Float Service)
→ Filter: SCHEDULING (due ≤ today) or RETRY (always)
→ Build FloatCollectionEvent{Process, Float, Runtime}
→ SQS: float-collections-daily-queue
→ Float Service daily-collections Lambda consumes
Webhook Collection (POST /qa/simulate/floats/webhook)
Simulates inbound webhook events that trigger float collection outside the daily scheduler.
Creates a FloatCollectionWebhookEvent{user_id} for each supplied user and sends them to the webhook collection SQS queue.
Async: Yes — SQS messages are sent and the endpoint returns immediately.
Request body:
{
"user_ids": ["uuid-1", "uuid-2"]
}
SQS target: FloatCollectionsWebhookQueueURL
Use case: Test the webhook-driven repayment path (e.g., bank ACH return callbacks) without waiting for the daily scheduler window.
LOC Collections (POST /qa/simulate/loc/collections)
Simulates the Line of Credit collection job by directly invoking the LOC Service Lambda function.
Unlike the subscription and float simulations, this endpoint does not send SQS messages — it performs a synchronous (fire-and-forget) async Lambda invocation using InvocationType: Event.
The Lambda executes independently; the endpoint returns immediately after the invocation is dispatched.
Async: Fire-and-forget Lambda invoke — the endpoint returns 200 after the invocation is dispatched, before the Lambda completes.
Request body:
{
"process": "due",
"look_ahead_days": 3
}
Process types:
process value |
Meaning |
|---|---|
|
Collect payments that will become due within |
|
Collect payments due today |
|
Collect payments past their due date |
|
Retry previously failed collection attempts |
look_ahead_days: Optional integer.
Relevant for the upcoming process type to control how far ahead the job looks for due payments.
Ignored for other process types.
Target Lambda: test-loc-service-loc-collections-job
Use case: Trigger LOC collection processing against specific test accounts without waiting for the production CloudWatch scheduled event.
Event Injection (POST /qa/test/event)
A low-level utility endpoint that injects arbitrary JSON payloads directly into Kinesis streams or SQS queues. This is used for debugging, for simulating third-party callback events (such as payment processor webhooks arriving on a Kinesis stream), and for driving any queue-consuming Lambda that does not have a dedicated simulation endpoint.
Request body:
{
"service": "kinesis",
"target": "prod-payments-stream",
"event": { "type": "payment.completed", "amount": 9.99 },
"partition_key": "user-uuid-1"
}
Parameters:
| Field | Type | Required | Description |
|---|---|---|---|
|
|
Yes |
Destination service type |
|
string |
Yes |
Stream name (Kinesis) or queue name (SQS) |
|
object |
Yes |
Arbitrary JSON payload — sent as-is |
|
string |
No |
Kinesis shard partition key; ignored for SQS |
Routing by service type:
service |
How target is resolved |
SDK call used |
|---|---|---|
|
Used directly as the stream name in |
|
|
Queue URL constructed from AWS account + region + queue name |
|
Use cases:
-
Inject a Kinesis payment callback event to test the payments processing pipeline end-to-end.
-
Send a crafted message to an SQS queue to exercise a specific Lambda error-handling branch.
-
Reproduce a production event shape in a test environment without waiting for a real external trigger.