Payment Processing Requirements
This section outlines the requirements for implementing payment processing endpoints.
Idempotency
All payment operations must be idempotent. Flex uses the flex_payment_id as an idempotency key.
Requirements
- If Flex sends a payment request with a
flex_payment_idthat already exists, return the existing payment (do not create a duplicate) - The
flex_payment_idis unique across all payments, not just per account - Store the
flex_payment_idpermanently and use it for deduplication
Example Scenario
Request 1: PUT /payment/flex_pay_123 → Creates payment, returns 200
Request 2: PUT /payment/flex_pay_123 → Returns existing payment, 200 (no duplicate)
Request 3: PUT /payment/flex_pay_456 → Creates new payment, returns 200
Payment Lifecycle
Payments progress through the following statuses:
┌─────────────┐
│ processing │ ← Initial state when payment accepted
└──────┬──────┘
│
├─────────────────┬─────────────────┐
▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ succeeded │ │ failed │ │ canceled │
└─────────────┘ └─────────────┘ └─────────────┘
Status Definitions
| Status | Description |
|---|---|
processing | Payment has been accepted and is being processed |
succeeded | Payment was successfully applied to the account |
failed | Payment failed (see failure_reason for details) |
canceled | Payment was canceled before completion |
Status Transition Rules
- Payments start in
processingstatus - From
processing, a payment can transition tosucceeded,failed, orcanceled - Terminal states (
succeeded,failed,canceled) are final and cannot change
Timestamps
initiated_at
- Set when the payment is first accepted by the partner's system
- Required for all payments
- Format: ISO 8601 with timezone (e.g.,
2025-11-15T14:22:10Z)
posted_at
- Set when the payment is successfully posted to the account ledger
nullwhile payment isprocessing- Required when status is
succeeded - Format: ISO 8601 with timezone
Batch Processing
Flex groups payments into batches for reconciliation purposes.
flex_batch_id
- Provided by Flex on every payment request
- Partners should store this value for reconciliation
- Multiple payments may share the same
flex_batch_id - Format: String (e.g.,
BATCH-20251115)
Error Handling
failure_reason
When a payment fails, include a human-readable error message:
{
"payment_id": "partner_123",
"flex_payment_id": "flex_pay_abc",
"status": "failed",
"failure_reason": "Account is closed and not accepting payments."
}
Common Failure Reasons
- Account not found or inactive
- Payment amount exceeds maximum allowed
- Duplicate payment detected (different from idempotent retry)
Payment Amount
amount_in_cents
- All monetary amounts are in cents (integer)
- Example:
$157.50is represented as15750 - Must match the amount in the original request
Polling for Status
Flex polls the Get Account Payment endpoint to check payment status.
Expected Behavior
- Partners should update payment status as soon as it changes
- Flex may poll frequently while payment is
processing - Once a terminal status is reached, Flex stops polling