FurlPay Docs
Open App
  • Services & Availability
  • Quickstart
  • For AI Agents
  • Monorepo
  • API Routes
  • Authenticationupdated
  • Webhook Eventsupdated
  • Error Codesupdated
  • Rate Limitsnew
  • Configuration & Setupnew
  • Merchant Paymentsnew
  • Payroll & Payoutsnew
  • Agentic Payments (x402)updated
  • Agent Trust & Mandates (TAP)updated
  • CCTP Cross-Chainupdated
  • LI.FI Swapsupdated
  • FurlPay Travels (Travel MCP)updated
  • Solana Actions & Blinks
  • Settlement Workspacenew
  • FURL Tokennew
  • Claude Connectorupdated
  • AI Assistants
  • Circlenew
  • Ramp Providersnew
  • Telegram Mini Appnew
  • Stripe Crypto
  • Persona KYC
  • Regulatory status
  • Screening & Casesnew
  • Security Postureupdated
  • Signing & WebAuthnupdated
  • Help Center
  • Getting Started
  • KYC Verification
  • Passkeys & Biometrics
  • Privacy & Data Protection
  • Transaction Statuses
  • Gasless Transfers
  • Deposits & Withdrawals
  • Managing Virtual Cards
  • Freezing & Unfreezing Cards
  • Declined Transactions
  • SDK & API Support
  • x402 Monetization Basics
  • Booking Travel
  • Travel Refunds & Cancellations

Resources

  • Changelog
  • System Status
  • OpenAPI Spec
  • Community
  • GitHub
Docs/Architecture/Configuration & Setup

Architecture

Configuration and deployment setup

Most of what FurlPay can do on a given deployment is decided by configuration: which credentials are present, which database migrations are applied and which money flags are on. This page is the map. The full variable list with comments is apps/web/.env.example.

Unset means unavailable, not simulated

In development, a missing credential usually selects an in-memory or demo path so the app runs with nothing configured. In production the same missing credential makes the route return 503. Setting INTEGRATION_MODE=live does not make an unbuilt integration real.

The three layers of gating

ParameterTypeDescription
Integration moderequiredINTEGRATION_MODEDeployment-wide. "live" permits real provider calls; anything else is mock. Production without live mode fails closed on money paths.
Financial environmentrequiredFURLPAY_ENVdevelopment, staging or production. Separate from NODE_ENV, because a preview build also has NODE_ENV=production and must not be treated as a place where real money moves.
Money flagsrequired*_LIVEOne switch per capability, default off. A flag reports on only when it is enabled, allowed in this environment, has every required credential, and the kill switch is not engaged.

FURLPAY_MONEY_KILL_SWITCH disables every money capability at once and is checked before any flag. FURLPAY_FROZEN_API_PREFIXES freezes named API prefixes with a 503 without a deploy.

Money flags

ParameterTypeDescription
ONCHAIN_BALANCES_LIVEoptionalcan enableRead balances from chain nodes. Read-only; allowed in development.
HARDWARE_WALLET_LIVEoptionalcan enableSigning with an external hardware wallet. No credentials required.
ONCHAIN_SETTLEMENT_LIVEoptionalneeds credentialsBroadcast settlement transactions. Needs FURLPAY_KMS_PROVIDER and ARBITRUM_RPC_URL.
BROKERAGE_LIVEoptionalneeds credentialsRoute orders to the brokerage. Needs the Alpaca key pair. Off means order submission returns 503.
AI_TRADING_LIVEoptionalneeds credentialsAgent-submitted trades within a policy. Needs the Alpaca key pair.
TOKENIZED_STOCKS_LIVEoptionalneeds registryNeeds a human-verified token registry, which ships empty.
ARC_RAIL_LIVEoptionalnot implementedNo Arc signer is wired and no FurlPay contract is deployed to Arc.
CARD_ISSUING_LIVEoptionalnot implementedNo card issuer is integrated.
BANKING_LIVEoptionalnot implementedNo banking or payment-aggregator partner is contracted.
ONRAMP_LIVE / OFFRAMP_LIVEoptionalnot implementedNo provider capability row is live; no verified-beneficiary path.
CREDIT_LIVE / BILL_PAY_LIVEoptionalnot implementedNo lender and no biller network.
REWARDS_LIVE / P2P_LIVEoptionalnot implementedNo rewards ledger; peer-to-peer state is not durable.
RECURRING_INVESTING_LIVEoptionalnot implementedSchedules are not durable and no worker executes them.
ACCOUNT_SPEND_LIVEoptionalnot implementedNo rail delivers value debited from an account balance.
DEFI_COLLATERAL_LIVE / CROSS_CHAIN_STOCKS_LIVEoptionalnot implementedNo collateral risk engine; no transfer-restriction checks.

A flag marked not implemented can never report on, whatever the environment says. Admins can see every flag and the names of any missing credentials at GET /api/ops/readiness.

Core platform

ParameterTypeDescription
FURLPAY_SESSION_SECRETrequiredsecretSession signing key. Production refuses to start signing sessions without it.
FURLPAY_RP_ID / FURLPAY_ORIGINrequiredconfigPasskey relying-party ID and origin. Never read from the request Host header.
SUPABASE_URL / SUPABASE_SERVICE_ROLE_KEYrequiredsecretPostgres through Supabase. The service-role key is server-only; row-level security is on with no public policies.
UPSTASH_REDIS_REST_URL / _TOKENrequiredsecretDurable key-value store: challenges, rate limits, webhook de-duplication, locks, operational controls. KV_REST_API_URL and _TOKEN are also honoured.
FURLPAY_ADMIN_EMAILrequiredconfigThe only account allowed to hold the admin role.
CRON_SECRET / FURLPAY_CRON_SECRETrequiredsecretScheduled-job credentials. With neither set, every cron request is refused.
FURLPAY_DATA_PLANEoptionalconfigPreview isolation. A Vercel deployment that is not production gets no database or key-value credentials unless its scope sets this to "isolated", and never a production database. Leave unset in production.
PUBLIC_API_ORIGIN / FURLPAY_TRUSTED_PROXY_HOPSoptionalconfigNeeded only behind a reverse proxy other than Vercel.

The key-value store is a hard dependency

Rail status, rate limits and x402 controls all read the key-value store. If it is over its plan limit or unreachable, those endpoints answer 503 controls_unavailable rather than guessing. Treat a rail as unavailable until the status endpoint answers again.

Integrations by area

ParameterTypeDescription
Sign-inoptionalGOOGLE_CLIENT_ID, TWILIO_*Google sign-in and one-time codes by SMS or email.
EmailoptionalRESEND_API_KEY, EMAIL_FROMTransactional email. The sending domain must be verified.
PushoptionalFURLPAY_VAPID_*, FURLPAY_FCM_SERVICE_ACCOUNTWeb push and Android push for approval prompts.
Identity checksoptionalPERSONA_*, SUMSUB_*Chosen with COMPLIANCE_IDENTITY_PROVIDER.
ScreeningoptionalCIRCLE_COMPLIANCE_API_KEY, COMPLYADVANTAGE_*Layers on top of the built-in sanctions list.
Circle walletsoptionalCIRCLE_W3S_API_KEY, CIRCLE_W3S_APP_IDBoth required, or the wallet routes return 503.
SigningoptionalFURLPAY_KMS_PROVIDER, TURNKEY_*Only "turnkey" is implemented. "env" is development-only and refused in production. Other values are refused by name.
Chain nodesoptional*_RPC_URLPer network, each with an optional _FALLBACK. Public endpoints are the default and are rate limited.
SwapsoptionalLIFI_API_KEY, LIFI_FEELI.FI routing. Quotes work without a key at low rate limits.
x402optionalFACILITATOR_EVM_ADDRESS, X402_*Facilitator settlement. A raw private key is refused in production; signing goes through the KMS provider.
RampsoptionalFURLGATEWAY_*, FURLBRIDGE_*Coinbase and Transak. See the ramp provider page.
CardsoptionalRAIN_*, FURLPAY_CARDAUTH_ENDPOINT_SECRETIssuer adapter and authorisation webhook. Setting these does not enable card issuing.
TraveloptionalDUFFEL_API_KEY, TRIPADVISOR_API_KEY, GOOGLE_PLACES_API_KEYInventory and content. A test-mode booking key is refused in production.
MarketsoptionalALPACA_*Brokerage and market data.
Payments (Stripe)optionalSTRIPE_*Optional Stripe payment intents and webhook.
PayrolloptionalFURLPAY_ROUTER_ADDRESS_*, FURLPAY_TAX_ENCRYPTION_KEYRouter address per network and the key that seals tax records.
Merchant collectionoptionalSUI_GRAPHQL_URL, FURLPAY_TESTNET_COLLECTIONSui reads, and testnet collection outside production only.
On-chain dataoptionalALLIUM_*, ONCHAIN_*, USDC_INDEX_*Ingestion and index settings for the on-chain dashboards.
TelegramoptionalTELEGRAM_BOT_TOKEN, TELEGRAM_WEBHOOK_SECRETMini App sign-in and bot webhook.
Community botsoptionalDISCORD_*Market brief, price cards and member welcome jobs.

Server-side limits

  • FURLPAY_MAX_SWAP_USD, FURLPAY_MAX_CCTP_USD, FURLPAY_MAX_TRANSFER_USD — per-transaction caps. Each defaults to 500 USD when unset.
  • FURLPAY_3DS_CHALLENGE_USD — amount at which an out-of-band approval is required.
  • FURLPAY_AGENT_HITL_THRESHOLD_USD — agent-key spends at or above this always need a person. Default 3,000 USD.
  • SETTLEMENT_* — settlement circuit-breaker thresholds.
  • FURLPAY_MIN_CLIENT_VERSIONS — minimum app versions allowed on money routes.

Database migrations

Migrations are numbered SQL files in supabase/migrations and are applied in order. A feature whose migration is missing reports its storage as unavailable; it does not fall back to memory in production.

ParameterTypeDescription
0001 – 0030requiredplatformAccounts, durability, ledger, payments, notifications, hotels, webhook events, analytics, usernames, control-plane approvals.
0031 – 0036requiredplatformFunction-execute revocation, on-chain ingestion, asset snapshots and index, CCTP records, USDC index.
0037optionalsettlementSettlement workspace draft records.
0038optionalsettlementBusiness onboarding state and the private document bucket.
0039optionalcomplianceCompliance cases.
0040optionalpaymentsMerchant payment links, destinations, intents, receipts, events and the webhook outbox.
0041optionalpaymentsMerchant webhook endpoints and the delivery claim function.
0042optionalpayroll, paymentsPayroll rosters and runs, merchant pricing tiers, operator notes, reconciliation alerts.
0043optionalpaymentsSui collection: widens the network checks and accepts Sui addresses.
0044optionalpayrollContractor invitations, account linking, wallet-proven payout addresses.
0045optionalpaymentsMerchant refunds.
0046optionalpaymentsLiveness alerts for collection.
0047optionalpaymentsArc testnet collection, booked to separate testnet ledger accounts.
0048optionalpayrollExcluding flagged recipients; journaling the payroll fee.
0049optionalsitePartnership inquiries.
0050optionaltelegramTelegram account links.

Scheduled jobs

Every job authenticates with Authorization: Bearer <CRON_SECRET> or x-furlpay-cron-key: <FURLPAY_CRON_SECRET>.

ParameterTypeDescription
/api/cron/reconcilerequireddaily, scheduledLedger reconciliation.
/api/cron/healthrequireddaily, scheduledProvider and scheduler health, including a live read against the key-value store; raises alerts.
/api/cron/market-briefoptionaldaily, scheduledPosts the market brief to Discord and Telegram.
/api/cron/price-cardsoptionaldaily, scheduledPosts price cards to Discord.
/api/cron/discord-welcomeoptionaldaily, scheduledGreets new community members.
/api/cron/settlement-safetyrequireddaily, scheduledSettlement circuit-breaker checks.
/api/cron/onchain-reconcileoptionaldaily, scheduledReconciles on-chain ingestion.
/api/cron/merchant-paymentsoptionalevery 2 minutes, scheduledRescans open checkouts and delivers merchant webhooks.
/api/cron/merchant-reconcileoptionalevery 10 minutes, scheduledMerchant and payroll reconciliation; raises alerts only.
/api/cron/onchain-nodeoptionalnot scheduledOn-chain node ingestion.
/api/cron/usdc-indexoptionalnot scheduledUSDC index maintenance.
/api/cron/ramp-maintenanceoptionalnot scheduledExpires stale ramp orders and retries partner callbacks. Needs to run every few minutes.
/api/cron/price-alertsoptionalnot scheduledEvaluates user price alerts.

"Scheduled" means the job is listed in apps/web/vercel.json, which has nine entries. The others exist as endpoints and need an external scheduler. Schedules more frequent than daily depend on the hosting plan; the AWS deployment schedules the same jobs with EventBridge.

Running locally

bash
npm install
cp apps/web/.env.example apps/web/.env.local   # every value may stay blank
npm run dev                                    # starts the web app

With nothing configured the app uses in-memory stores and development-only demo paths. Before a production build, the claims check (npm run check:claims) runs automatically and fails the build if public copy describes an unavailable capability as available.

Did this page help?
Edit this page on GitHub

← Previous

Rate Limits

Next →

Merchant Payments