Blocklist

The blocklist prevents future payment processing for users whose ACH payments were returned with codes indicating a structural account problem (closed, frozen, or invalid). It is separate from fraud — a blocked user’s account simply cannot receive or send ACH payments until they provide a new bank account.

How the Blocklist Works

Two Lambdas manage the blocklist:

  • blocklist-handler — Consumes payment events from the prod-payments Kinesis stream and auto-blocks users on specific return codes.

  • blocklist-remover — Consumes SQS events and removes a user’s block when they update their bank account.

The blocklist-handler writes BLOCKED records to DynamoDB when a structural return code is received. The blocklist-remover writes NOTBLOCKED records when a user updates their bank account. A user’s current blocklist state is determined by the most recent record for their user_id.

Auto-Blocking Flow

The blocklist-handler Lambda receives all payment events from the prod-payments Kinesis stream. It acts only on SUBSCRIPTION_RETURNED and FLOAT_DEBIT_RETURNED event types, ignoring all others.

prod-payments Kinesis Stream
 │  event types: SUBSCRIPTION_RETURNED, FLOAT_DEBIT_RETURNED
 ▼
blocklist-handler (Lambda)
 │  decode payment event
 │  check return_code
 │
 ├─ R02 / R03 / R04 / R16 ──► write BLOCKED record to blocklist DynamoDB
 │  AC04 / BE01 / AC01 / AC06
 │
 └─ all other codes ──► discard (no DynamoDB write)

Only SUBSCRIPTION_RETURNED and FLOAT_DEBIT_RETURNED events are processed. Other event types (e.g. FLOAT_CREDIT_*) are silently ignored.

Unblocking Flow

When a user updates their bank account, the caller publishes an event to the prod-payments-service-blocklist-remove SQS queue. The blocklist-remover Lambda processes this event and writes a NOTBLOCKED record for the user.

Caller (other FloatMe service)
 │  publish bank account updated event
 ▼
SQS (blocklist-remove queue)
 │
 ▼
blocklist-remover (Lambda)
 │  parse user_id + account_id from event
 │  write NOTBLOCKED record
 ▼
Blocklist DynamoDB

The account_id (Plaid account ID) is stored as the trigger_id on the unblock record for audit purposes.

Return Code Reference

Code Provider Meaning Blocklist Action

R02

Usio (NACHA)

Account closed

BLOCKED

R03

Usio (NACHA)

No account / unable to locate account

BLOCKED

R04

Usio (NACHA)

Invalid account number structure

BLOCKED

R16

Usio (NACHA)

Account frozen

BLOCKED

AC04

JPM

Account closed (maps to R02)

BLOCKED

BE01

JPM

No account / unable to locate account (maps to R03)

BLOCKED

AC01

JPM

Invalid account number structure (maps to R04)

BLOCKED

AC06

JPM

Account frozen (maps to R16)

BLOCKED

All other codes

Any

e.g. R01 (NSF), R09 (insufficient funds)

Discarded — no DynamoDB write; user remains unblocked

Only SUBSCRIPTION_RETURNED and FLOAT_DEBIT_RETURNED event types are evaluated for blocklisting. Returns on other payment types (e.g. float credits) do not trigger this logic.

API Endpoints

The blocklist status and history for a user are available via the REST API:

  • GET /{user_id}/payments/blocklists — current blocklist status

  • GET /{user_id}/payments/blocklists/history — full blocklist history

  • POST /{user_id}/payments/blocklist — manually add a user to the blocklist

  • DELETE /{user_id}/payments/blocklist — manually remove a user from the blocklist

See API Specification for request/response schemas.

  • Payment Syncing — How payment return events flow from processors into the Kinesis stream

  • Event Flows — Kinesis event types published by the payments service

  • JPM Integration — JPM return code mappings (AC04, BE01, AC01, AC06)

  • Usio Integration — Usio NACHA return codes and return rate thresholds

  • Prenotes — Prenote returns can also carry blocklist-triggering codes