Integration Users

The QA API exposes two endpoints for creating integration test users. The predefined states approach is quick and opinionated — you pick a named state and the service wires up a complete, realistic user behind the scenes. The custom users approach is flexible and JSON-driven — you supply every field explicitly and the service writes only what you describe.

Both endpoints return a user_id that can be stored and reused across test scenarios.

Predefined States (POST /qa/integration/user)

A predefined state is a named configuration that sets up a complete user in a specific condition — for example float_ready (bank account connected, income detected, float eligibility confirmed) or banned (account created and immediately banned in User Service).

The request body requires three fields:

Field Description

email

Email address for the new user. Must be unique.

password

Initial Auth0 password.

state

One of the enumerated state names (see below).

38 named states are defined, plus the sub_overdue_<N>d wildcard (any positive integer N). The full list with descriptions is in Predefined States.

Predefined states are opinionated by design. Bank account institution, starting balance, transaction history depth, and float limits are all chosen by the handler. Use custom users when you need to control those parameters.

Custom Users (POST /qa/integration/custom-user)

The custom user endpoint accepts a single JSON object whose top-level keys correspond to independent subsystems. Only user and plaid are required; all other sections are optional and are silently skipped when absent.

user — Base User Profile

Field Required Description

first_name

yes

First name. A random value is generated when left blank.

last_name

yes

Last name. A random value is generated when left blank.

email

yes

Email address. If empty, a unique qa<random>@integrationtest.floatme.io address is generated.

password

yes

Auth0 password.

phone_number

yes

Phone number string (digits only). Defaults to 2108519644 when not supplied.

address, city, state, zip_code

yes

Residential address. Each defaults to a random fake value when empty.

date_joined

yes

ISO-8601 timestamp of account creation.

status

yes

Initial account status. Accepted values: ACTIVE, BANNED, PAUSED, REACTIVATE, INACTIVE, PENDING_CANCELLATION. Status mutations are applied after all other data is written.

is_phone_verified, sms_authorized, email_verified

yes

Verification flags written to the Auth0 and User Service profiles.

user_id

no (output)

Populated by the service after creation. Returned in the response body.

plaid — Bank Account Configuration

Controls the Plaid sandbox item linked to the user. override_accounts, credit_accounts, student_accounts, institution_id, invalid, and removed are all required fields on the object (arrays may be empty).

Field Description

override_accounts

Array of depository accounts (checking, savings). Each account specifies type, subtype, starting_balance, is_main, and an array of transactions. Optional past_balances entries are written to the Transactions Service after the item is linked.

credit_accounts

Array of credit card accounts with APR, payment amounts, and transactions. When non-empty, a Plaid liabilities webhook is fired after item creation.

student_accounts

Array of student loan accounts. Also triggers the liabilities webhook when non-empty.

institution_id

Plaid institution ID to associate with the item (e.g. ins_3 for Huntington).

invalid

When true, ResetLogin is called after item creation to put the item in a reconnect-required state.

removed

When true, all Plaid items are force-removed after creation.

When all three account arrays are empty no Plaid item is created and no webhook is fired.

subscriptions — Subscription Records

An array of subscription records written directly to the Subscription Service, bypassing the normal billing pipeline. Each record maps to a QASubscription object.

Field Required Description

subscription_id

yes

Unique identifier for the subscription record.

subscription_date

yes

Billing date (RFC 3339).

subscription_amount

yes

Amount as a string (e.g. "4.99").

subscription_status

yes

Current status (e.g. COMPLETED, ERROR, PAUSED_SKIPPED, SCHEDULING).

subscription_period

yes

Billing period in MM/YYYY format.

created_date

yes

Record creation timestamp (RFC 3339).

payments

no

Array of QAPayment objects. ACH payments generate two history entries (ACHSENT then COMPLETED/ERROR); PINLESS payments generate one. Payment records are also forwarded to the Payments Service via PostQaPayments.

floats — Float Records

An array of advance (float) records written directly to the Float Service. Floats are added after all concurrent steps complete because scheduling a float can interfere with debit card and bank account setup.

Field Required Description

amount

yes

Float amount (e.g. 20.00).

fee

yes

Fee charged for the advance.

type

yes

Advance type: PINLESS or NORMAL.

credit_status, debit_status

yes

Current credit and debit leg statuses.

credit_date, debit_date

no

Scheduled or actual settlement dates (RFC 3339).

created_date

yes

Record creation timestamp (RFC 3339).

evaluation_id

yes

Underwriting evaluation ID linked to this advance.

payments

no

Array of QAFloatCollection objects representing historical collection attempts.

loans — LOC Loan Records

An array of line-of-credit loan records written to the LOC Service. Each loan may include installment schedules and payment records. Payments are created as a second call to QACreatePayments after the loan itself is written.

Field Required Description

loan_id

yes

Unique loan identifier.

loan_amount, total_amount, current_balance

yes

Monetary amounts in cents.

fee_amount, fee_percent

yes

Fee configuration.

status

yes

Loan status (e.g. ACTIVE, COMPLETED, PAST_DUE).

auto_pay_enabled

yes

Whether autopay is enabled for the loan.

installments

yes

Array of installment records, each with due_date, status, total_amount, and payment_applications.

payments

no

Array of QALocPayment objects written after the loan is created.

float_profile — Underwriting Float Profile

Sets the user’s float eligibility configuration in the Underwriting Service, including the maximum float limit and whether LOC loans are enabled.

Field Required Description

limit

yes

Maximum float limit in dollars (e.g. 20, 50, 80, 100, 200).

loan_limit

yes

Maximum LOC loan limit.

is_loan_enabled

yes

Whether LOC products are available to this user.

is_float_enabled

no

Whether float advances are available. Defaults to true.

debit_card — Payment Card Configuration

An array of debit card records added to the Payments Service. The first card marked is_primary: true (or the first card in the array if none is marked) is registered as the primary card type ALL. Subsequent cards use type NONE.

Field Required Description

works

yes

When false, toggle_failure is set on the card so that payment attempts fail.

invalid

no

When true, the card is marked invalid via AdminUpdateDebitCard.

is_primary

no

Designates the primary card. First card in the array is used as primary if none is flagged.

income — Employment / Income Record

Creates an employment record in the Insight Service. Income is added after floats to avoid it being overwritten when a bank account connection triggers an institution-change handler.

Field Required Description

name

yes

Employer name.

frequency

yes

Pay frequency (e.g. Monthly, BiWeekly).

initial_payday

yes

First payday date string.

pay_type

yes

Pay type (e.g. Salary, Hourly).

iterable — Push Notification Device Registration

Registers a mobile device token with Iterable for push notification testing.

Field Required Description

device.token

yes

Firebase device token.

device.platform

yes

GCM (Android) or APNS (iOS).

device.application_name

yes

Push integration name configured in Iterable.

device.endpoint_enabled

no

Whether the push endpoint is active.

device.notifications_enabled

no

Whether notifications are enabled for this device.

device.data_fields.phone_type

no

Device model or phone type string.

Orchestration

The diagram below shows the full creation flow for a custom integration user.

integration user creation

Downstream Effects

The CreateCustomIntegrationUser handler writes to downstream services in the following order:

  1. Auth0createUser() registers the account and returns an auth0_user_id. The FloatMe user ID is extracted from the Auth0 ID by splitting on |.

  2. User ServicecreateUserInFloatmeAPI() invokes the user-handler-floatme-test Lambda directly (bypassing API Gateway) to create the user profile record. These two steps are sequential and must complete before anything else proceeds.

  3. The following steps run concurrently via executeConcurrently():

    • PlaidaddPlaid() creates a sandbox Plaid item and saves it via the Transactions Service. Past balance records are written after the item is linked. Invalid/removed flags trigger additional Plaid sandbox calls.

    • Payments ServiceaddDebitCards() registers each debit card. The primary card is added first; non-primary cards use an exponential backoff retry policy.

    • Subscription ServiceaddSubscriptions() writes subscription records including full payment history.

    • Payments Service (payments) — addPayments() posts subscription payment records to the Payments Service.

    • Underwriting / Float ServiceupdateFloatProfile() creates the float eligibility profile.

    • LOC ServiceaddLocLoans() creates loan records and then loan payment records.

    • IterableaddIterableUser() registers the device token for push notifications.

  4. Float ServiceaddFloats() writes advance records. This step runs after the concurrent block because scheduling a float can block debit card and bank account setup.

  5. Insight ServiceaddIncome() creates the employment record. A short sleep precedes this step to prevent the income record from being deleted when a bank account event fires the institution-change handler.

  6. User Service (status) — handleCustomUserStatus() applies any requested account status mutation (ban, pause, close, clear) as the final step.

Bypass rules are not written by the custom user handler. They are written by specific predefined state handlers (e.g. float_ready_bypass, multiple_items) via createBypass(), which saves a RequirementsByPass record directly to DynamoDB through the BypassRepo.