What This Reference Covers
This comprehensive guide provides everything you need to handle payment statuses correctly:- Status lifecycles: The complete flow from creation to terminal states
- The pending threshold: Why
pendingstatus is the point of no return - Failed vs reversed: Critical distinction between pre-funding and post-funding failures
- ACH return codes: All R-codes and S-codes with their meanings and timing
- Status reasons: Complete catalog of failure reasons and their sources
- Status/Source/Reason matrix: Valid combinations showing what actually occurs
- Implementation patterns: Code examples for monitoring and handling status changes
Payment Lifecycle Overview
The happy path for payments follows this progression:1
Created
Payment successfully created and awaiting verification
2
Scheduled
Payment passed verifications and risk scoring, queued for processing
3
Pending
Payment sent to network - CANNOT BE STOPPED
4
Paid
Payment successfully funded
Status Values
Complete Status Reference
| Status | Description | Can Modify? | Terminal? |
|---|---|---|---|
created | Payment created, awaiting verification | ✅ | No |
scheduled | Verified and queued for processing | ✅ | No |
pending | Sent to network | ❌ | No |
on_hold | Paused for review | ✅* | No |
paid | Successfully funded | ❌ | No† |
failed | Declined/returned before funding | ❌ | Yes |
reversed | Returned after funding completed | ❌ | Yes |
cancelled | Terminated before network submission | ❌ | Yes |
†Can still transition to
reversed if return occurs post-funding
Understanding Failed vs Reversed
| Status | When It Occurs | Money Movement | Example |
|---|---|---|---|
failed | Before funding completes | Funds deposited in your account | NSF during processing |
reversed | After funding completes | Funds deposited then withdrawn from your account | Dispute filed after payment |
Status Sources
Sources identify where status changes originate:| Source | Description | When Used |
|---|---|---|
system | Automated system processing | Normal status progression (created → scheduled → pending → paid) |
watchtower | Internal fraud/risk system | Balance checks, fraud screening, validation failures |
bank_decline | ACH network return | Returns from banks |
customer_dispute | Customer disputed with their bank | Unauthorized claims (R05, R07, R10, R11, R29) |
user_action | Manual action via API | User-initiated holds, cancels, releases |
Status/Source/Reason Matrix
Success States
| Status | Source | Reason | Context |
|---|---|---|---|
created | system | ok | Payment created and awaiting verification |
scheduled | system | ok | Payment validated and scheduled |
pending | system | ok | Payment submitted to ACH network |
paid | system | ok | Payment successfully funded |
Hold States
| Status | Source | Reason | Context |
|---|---|---|---|
on_hold | watchtower | risk_review | Flagged by risk system (paykey or customer under review) |
on_hold | watchtower | amount_too_large | Exceeds max transaction or daily limits |
on_hold | user_action | user_request | Manually held by user via API |
Failed States (Pre-Funding)
| Status | Source | Reason | Context |
|---|---|---|---|
failed | watchtower | insufficient_funds | Pre-submission balance check detected insufficient funds |
failed | watchtower | payment_blocked | Blocked by Straddle fraud screening |
failed | watchtower | invalid_paykey | Paykey validation failed (blocked, restricted, or customer not found) |
failed | watchtower | payment_stopped | Payment rail assignment failed |
failed | watchtower | duplicate_entry | Duplicate payment detected during ID assignment |
failed | bank_decline | insufficient_funds | ACH return R01/R09 |
failed | bank_decline | closed_bank_account | ACH return R02 |
failed | bank_decline | invalid_bank_account | ACH return R03/R04/R20 |
failed | bank_decline | invalid_routing | ACH return R13 |
failed | bank_decline | frozen_bank_account | ACH return R16 |
failed | bank_decline | owner_deceased | ACH return R14/R15 |
failed | bank_decline | payment_stopped | ACH return R08 |
failed | bank_decline | payout_refused | ACH return R23 |
failed | bank_decline | duplicate_entry | ACH return R24 |
failed | bank_decline | other_network_return | Other ACH return codes |
failed | customer_dispute | disputed | ACH return R05/R07/R10/R11/R29 (before funding) |
failed | user_action | user_request | Manually failed by user via API |
Reversed States (Post-Funding)
| Status | Source | Reason | Context |
|---|---|---|---|
reversed | bank_decline | insufficient_funds | Late ACH return R01/R09 |
reversed | bank_decline | closed_bank_account | Late ACH return R02 |
reversed | bank_decline | invalid_bank_account | Late ACH return R03/R04/R20 |
reversed | bank_decline | invalid_routing | Late ACH return R13 |
reversed | bank_decline | frozen_bank_account | Late ACH return R16 |
reversed | bank_decline | owner_deceased | Late ACH return R14/R15 |
reversed | bank_decline | payment_stopped | Late ACH return R08 |
reversed | bank_decline | payout_refused | Late ACH return R23 |
reversed | bank_decline | duplicate_entry | Late ACH return R24 |
reversed | bank_decline | other_network_return | Other late ACH returns |
reversed | customer_dispute | disputed | ACH return R05/R07/R10/R11/R29 (after funding) |
Cancelled States
| Status | Source | Reason | Context |
|---|---|---|---|
cancelled | user_action | user_request | Manually cancelled by user via API |
Cancellation only occurs via user action in the dashboard or API
Important: Same Reason, Different Sources
Some reason codes can originate from different sources depending on when they’re detected:insufficient_funds
| Source | When Detected | Description |
|---|---|---|
watchtower | Pre-submission | Balance check via Plaid detected insufficient funds before network submission |
bank_decline | Post-submission | ACH network returned R01/R09 after payment was submitted to bank |
- Watchtower: Proactive check using real-time balance data — payment never leaves Straddle
- Bank Decline: Reactive return from the ACH network after the payment was sent
Status Reasons
Active Reason Codes
These reason codes are actively used by the system:| Reason Code | Description | Sources |
|---|---|---|
ok | Normal/successful status | system |
insufficient_funds | Customer’s account has insufficient funds | watchtower, bank_decline |
closed_bank_account | Bank account is closed | bank_decline |
invalid_bank_account | Account cannot be located or is invalid | bank_decline |
invalid_routing | Invalid ACH routing number | bank_decline |
frozen_bank_account | Account frozen or OFAC hold | bank_decline |
owner_deceased | Account owner is deceased | bank_decline |
disputed | Customer notified bank payment was unauthorized | customer_dispute |
payment_stopped | Customer placed stop payment order | watchtower, bank_decline |
risk_review | Payment under review by Straddle | watchtower |
payment_blocked | Blocked by fraud screening | watchtower |
invalid_paykey | Paykey blocked due to previous failures | watchtower |
amount_too_large | Exceeds maximum allowed amount | watchtower |
duplicate_entry | Duplicate transaction detected | watchtower, bank_decline |
user_request | User-requested action | user_action |
other_network_return | Other network return codes | bank_decline |
payout_refused | Receiver refused credit | bank_decline |
ACH Return Codes
Standard ACH Returns (R-Codes)
| Code | Reason | Message |
|---|---|---|
| R01 | insufficient_funds | The customer’s account has insufficient funds |
| R09 | insufficient_funds | Uncollected funds |
| R02 | closed_bank_account | The bank account is closed |
| R03 | invalid_bank_account | The bank account could not be located |
| R04 | invalid_bank_account | Bank account number invalid (missing digits) |
| R13 | invalid_routing | Invalid ACH routing number |
| R20 | invalid_bank_account | Account not eligible for transaction activity |
| R05 | disputed | Debit to consumer account using corporate consent |
| R07 | disputed | Authorization revoked by customer |
| R10 | disputed | Customer advises not authorized |
| R11 | disputed | Check truncation entry return |
| R29 | disputed | Corporate customer notified bank unauthorized |
| R08 | payment_stopped | Customer placed stop payment order |
| R14 | owner_deceased | Representative payee deceased |
| R15 | owner_deceased | Beneficiary/account holder deceased |
| R16 | frozen_bank_account | Account frozen or OFAC hold |
| R23 | payout_refused | Receiver refused credit |
| R24 | duplicate_entry | Duplicate entry |
| R06+ | other_network_return | Various other return reasons |
Straddle Internal Codes (S-Codes)
| Code | Reason | Message | When Applied |
|---|---|---|---|
| S01 | payment_blocked | Invalid routing number | Pre-origination |
| S02 | payment_blocked | Known bad account number | Pre-origination |
| S10 | payment_blocked | Invalid account number | Pre-origination |
| S11 | payment_blocked | Previous R02, R03, R04, R16, or R20 | Pre-origination |
| S12 | payment_blocked | Previous R05, R07, R08, R10, R11, or R29 | Pre-origination |
| S13 | payment_blocked | Invalid ODFI credentials | Pre-origination |
Status Details Structure
Every payment includes detailed status information:Handling Status Changes
Monitoring for Status Changes
Handling Specific Failure Reasons
Common Scenarios
Successful Payment Flow
created→system/ok- Payment initializedscheduled→system/ok- Verification passed, risk approvedpending→system/ok- Sent to ACH networkpaid→system/ok- Funds successfully transferred
Pre-Submission Balance Check Failure
created→system/ok- Balance check detects insufficient funds
failed→watchtower/insufficient_funds- No money moved, payment never sent to bank
NSF After Submission (ACH Return)
created→scheduled→pending- Bank returns with R01
failed→bank_decline/insufficient_funds/ code: R01- No money moved (failed before funding)
Dispute After Funding
created→scheduled→pending→paid- Customer disputes with their bank
- Bank sends R10 return
reversed→customer_dispute/disputed/ code: R10- Money was moved, then returned
Risk Hold and Release
created→system/ok- Payment initialized- Watchtower flags for review
on_hold→watchtower/risk_review- Manual review in dashboard
- If approved: released →
scheduled→ normal flow - If declined: →
failedorcancelled
User-Initiated Hold
created→system/ok- User calls hold API
on_hold→user_action/user_request- User can release when ready
- Released → continues processing
Best Practices
Monitor Pending Status
Once pending, payments cannot be stopped. Plan accordingly.
Check Both Source and Reason
The same reason can come from different sources with different implications.
Handle Failed vs Reversed
Different workflows for pre-funding failures vs post-funding reversals.
Track Return Codes
Log ACH return codes for reconciliation and pattern analysis.
Next Steps
Webhook Events
Set up real-time status notifications
Testing Statuses
Test various status scenarios in sandbox
Charges Guide
Learn about charge-specific flows
Payouts Guide
Understand payout-specific scenarios