Payments
Create a payment to a verified handle, follow it from CREATED to CONFIRMED, and read your history. Two ways to fund it: a person's own wallet (checkout) or your Reward Vault.
| Source | Who signs | Assets | Use it for |
|---|---|---|---|
wallet | The payer's own wallet, at the checkout link FomoPay returns. Non-custodial. | USDG, ETH | Bounties, invoices, one-off payments a person approves |
vault | FomoPay's payout signer, spending your vault's approved allowance. | USDG | Automated payouts — rewards, prizes, referrals. Same as /v1/rewards |
Create a payment
/v1/paymentsscope payments:createrecipientstringrequired- The Fomo handle:
@lyra. Resolved server-side; anything notVERIFIEDis refused (states). amountdecimal stringrequired- In whole units:
"100","0.05". USDG has 6 decimals, ETH 18. Never a float. assetUSDG | ETHrequired- Token addresses are never accepted from requests — FomoPay uses its server-side registry (USDG is
0x5fc5…d168). network"robinhood"optional- Optional; the only network. Anything else is
422 UNSUPPORTED_NETWORK. source"wallet" | "vault"optional- Default
wallet.vaultrequiresvault_id. vault_idstringoptional- The Reward Vault to pay from (
vault_…). sender_wallet0x addressoptional- Wallet payments: lock the checkout to one paying wallet. Omit to let any signed-in wallet pay.
memostring ≤ 280optional- Shown on the receipt (“Logo bounty”). Stored off-chain.
reasonstring ≤ 280optional- Why it was paid (“FomoRun #42 Winner”).
type"DIRECT" | "REWARD"optional- Defaults to
DIRECTfor wallet andREWARDfor vault payments. metadataobject ≤ 4 KBoptional- Your own keys and values, returned on the payment and in webhooks.
visibilityprivate | unlisted | publicoptional- Receipt visibility. Default
unlisted(anyone with the link). Amounts are never published unless you choosepublic. confirmationsobjectoptional- Acknowledgements the risk engine may require:
similar_handle_acknowledged,recent_change_acknowledged,new_recipient_acknowledged,recipient_confirmed. Idempotency-Keyheaderoptional- Strongly recommended (the SDK always sends one). Same key + same body returns the original payment. Idempotency.
Once a transfer confirms it can't be reversed — not by you, not by FomoPay. A payment can be canceled only before it's submitted. Show the recipient's avatar, name and handle to whoever approves a payout.
Paying from a vault
Identical to POST /v1/rewards. The payment is executed by FomoPay's payout signer with transferFrom(vault, recipient, amount); you can watch it move through SUBMITTED → CONFIRMING → CONFIRMED.
When the risk engine steps in
| Outcome | What you get |
|---|---|
| Allowed | 201 with status: "CREATED". |
| Allowed, with warnings | 201 with warnings and risk.flags — a lookalike handle (SIMILAR_HANDLE), a first-time recipient. Show them in your own review step; people paying at the checkout are asked to acknowledge them before signing. |
| Needs a confirmation | 428 CONFIRMATION_REQUIRED with details.required — used for interactive senders. Retry with confirmations once a person has acknowledged. |
| Needs approval | 201 with status: "PENDING_APPROVAL" and approvals_required. A project Finance/Admin approves it in the dashboard. |
| Held | 201 with status: "HELD" and hold_until — e.g. the recipient changed their payout wallet recently (vault/API payouts wait out the cooldown). |
| Blocked | An error: PAYMENT_LIMIT_EXCEEDED, VAULT_INSUFFICIENT, COMPLIANCE_BLOCKED … see Errors. |
Lifecycle
| Status | Meaning |
|---|---|
CREATED | Recorded; recipient and destination snapshotted. Wallet payments wait at the checkout link. |
PENDING_APPROVAL | Over a project approval threshold — waiting for approvers. |
HELD | Paused by a risk rule until hold_until (or manual review). |
AWAITING_SIGNATURE | The exact transaction was prepared; waiting for the wallet to sign and send it. |
SUBMITTED | Broadcast to Robinhood Chain; tx_hash is known. |
CONFIRMING | Mined, waiting for the required confirmations. |
CONFIRMED | Confirmed on-chain and verified by FomoPay. Receipt number assigned; payment.confirmed sent. |
FAILED | Reverted, dropped/replaced, or failed verification. error says why in plain language. |
CANCELED | Canceled before submission. |
CONFIRMED is never optimistic. FomoPay waits for the chain's confirmations, then verifies the receipt succeeded, the sender is right (your vault's payout signer or the paying wallet), and — for USDG — that exactly one Transfer(from, recipient, amount) event matches the snapshot. ETH transfers must match recipient and value exactly.
Every payment is attributable on-chain. FomoPay appends a random 32-byte payment reference to the transfer calldata. ERC-20 decoding ignores the extra bytes (about 500 gas), and the reference ties the transaction to exactly one payment — a transaction hash can settle only one payment, ever.
The destination is frozen at creation. If @lyra changes her payout wallet after you create a payment, that payment still goes to the wallet verified when you created it (destination.verification_version). Nothing is silently redirected.
Retrieve a payment
/v1/payments/{payment_id}scope payments:readReading an in-flight payment also checks the chain, so polling is never staler than the chain itself. Prefer webhooks in production; for scripts the SDK has fp.payments.wait(id).
The payment object never contains the recipient's full wallet address — only destination.address_masked. explorer_url links the transaction on Robinhood Chain's explorer (it's null on the local development chain, which has none).
List payments
/v1/paymentsscope payments:readstatusstringoptional- One or more, comma-separated:
SUBMITTED,CONFIRMING. recipientstringoptional- A handle:
@lyra. typeDIRECT | REWARD | BULKoptionalassetUSDG | ETHoptionalsourcewallet | vaultoptionallimit1–100optional- Page size.
cursorstringoptional- The previous page's
next_cursor.
A recipient's payments
/v1/profiles/@{handle}/paymentsscope payments:readOnly your project's payments to that identity — never anyone else's, and never lifetime earnings. Financial privacy is the default.