The Payment Page
Overview
Every payment request generates a hosted payment page at:
https://app.tokencashflow.com/pay/{payment_id}This page is fully managed by TokenCashFlow — no embedding or custom frontend work required. Simply redirect your customer to the pay_url returned from POST /v1/payments.
The page is:
- Publicly accessible — no login required for the payer
- Mobile-first — designed for smartphones
- Real-time — status updates every 5 seconds
What the payer sees
1. Crypto selector (AWAITING_SELECTION)
The payer sees your enabled cryptos grouped by token. For each token available on multiple chains (e.g. USDT on Ethereum and USDT on Polygon), the chains are listed separately with an estimated network fee for each. The chain with the lowest estimated fee is highlighted with a "Recommended — Lowest fee" badge.
For each option the payer sees:
- Token symbol and name
- Logo
- Approximate USD equivalent of the required amount at the current live rate
- Estimated network fee (refreshed every 30 seconds; approximate only)
2. Rate lock (AWAITING_PAYMENT)
After selecting a crypto, the payer sees:
- The current exchange rate (e.g.
1 ETH = $2,000.00) - The exact crypto amount they must send (e.g.
You will send: 0.075000 ETH) - A Confirm and Pay button
Clicking Confirm locks the rate. The exact amount displayed is final for the duration of the chain selection window. A countdown timer starts at this point, tracking selection_expires_at.
3. Payment instructions (AWAITING_PAYMENT → PARTIALLY_PAID → CONFIRMING)
After rate lock the payer sees:
- The payment wallet address (text + QR code)
- The exact amount in crypto
- The expiry countdown timer
- Deep-link buttons: Open in MetaMask (EIP-681 URI) and Open in Wallet (for mobile wallets)
- Live status banner updating in real time
Rate locking
The rate is fixed when the payer clicks "Confirm and Pay". The locked rate is stored in the payment record. The exact crypto amount is calculated at lock time:
required_crypto_amount = amount_usd / locked_rate_usd(adjusted if fee_payer = payer — see your account's payment settings)
The rate is valid until the chain selection window expires (selection_expires_at). This window is set per-chain by the platform (chain.payment_expiry_minutes). The countdown timer on the payment page tracks this window — not a global payment expiry.
Payments never expire. A payer can always return to the payment link. Only the chain selection (rate lock window) expires. If it expires, the payer can reselect a token and get a new rate.
Selection expiry and reselection
When the chain selection window (selection_expires_at) passes:
- If no transaction is in progress → status becomes
EXPIRED_SELECTION - The payer can return to the payment page at any time and reselect a token (same or different) with the current market rate
- A new selection window starts on reselection
- If a transaction is already being confirmed, the expiry is held until the transaction resolves
The amber banner on the payment page reads:
"Your previous selection expired. Please select a payment method to continue."
Partial payments
If the payer sends less than the required amount:
- The page updates automatically to show:
"Partial payment received: 0.030 ETH. Remaining: 0.045 ETH (~$90.00 USD)" - The payer can top up the remaining amount to the same wallet address before
selection_expires_at - The remaining amount in crypto is calculated using the locked rate (not the current market rate)
If the chain selection window expires while in PARTIALLY_PAID state (and no unconfirmed tx):
- Status transitions to
EXPIRED_SELECTION - The payer must reselect to continue — a new rate is applied to the remaining USD amount
- Previously received funds are counted; only the remaining gap is recalculated at the new rate
- The page shows: "Selection expired — $XX.XX USD remaining. Reselect to pay at the current rate."
Partially paid payments are never permanently closed by expiry — the payer can always complete them.
Overpayments
If the payer sends more than the required amount:
- The payment proceeds to
CONFIRMING→COMPLETEDas normal - The excess crypto is absorbed by the platform — no refund is issued
- You are credited for the original
amount_usdonly, not the excess - A notice on the payment page informs the payer: "Overpayment is non-refundable"
Redirect after completion
When the payment reaches COMPLETED:
- The payer sees a success screen
- If you set a
redirect_urlwhen creating the payment, a 3-second countdown appears: "Redirecting in 3..." - The payer is then redirected to your URL
Your redirect URL receives no extra query parameters from TokenCashFlow by default. Use the webhook payment.completed event to update your system, not the redirect.
Payer support
Payers can click "Having issues? Contact support" on any payment page to open a support ticket without logging in. They must provide their email address so the admin team can reply.
Page states reference
| Payment status | Page display |
|---|---|
AWAITING_SELECTION | Crypto selector; amount; description (no countdown yet) |
AWAITING_PAYMENT | Wallet address; QR code; exact crypto amount; selection_expires_at countdown |
PARTIALLY_PAID | Remaining amount (~USD); wallet address; QR code; selection_expires_at countdown |
EXPIRED_SELECTION (no prior payment) | Amber banner: "Your previous selection expired — please reselect"; crypto selector |
EXPIRED_SELECTION (partial payment) | Amber banner with remaining USD; crypto selector |
CONFIRMING | "Payment received — confirming on blockchain"; progress indicator |
COMPLETED | Success state; redirect if configured |
BLACKLISTED | "Payment cannot be processed" (generic — blacklist reason not revealed) |
FAILED | Generic error message |

