# FintraPay API > FintraPay is a crypto payment gateway. It lets a business accept > stablecoin payments, send payouts, and withdraw balances across 7 > blockchains through one HTTP API. ## What it does - Accept stablecoin payments via hosted checkout or a direct API call - Send single and batch payouts to any external wallet - Withdraw custodial balances to your own registered wallets - Transfer balance to another FintraPay merchant instantly, off-chain - Earn interest on an idle custodial balance - Recurring billing via payment links, subscription plans and subscriptions - Per-user deposit addresses for exchange-style deposit flows ## Supported networks and assets Chains (7): TRON, BSC, Ethereum, Solana, Base, Arbitrum, Polygon Stablecoins (6): USDT, USDC, DAI, FDUSD, TUSD, PYUSD Not every token exists on every chain — 25 valid token/chain pairs in total. USDC on TRON is NOT supported: Circle discontinued it in February 2025. ## Pricing - Invoice fee: 0.4% of the invoice amount. - Withdrawal fee: network fee only. There is no flat withdrawal fee. - Payout fee: $0.01 flat plus the network fee, charged PER PAYOUT. A batch payout charges it per recipient, not once per batch. - Network (gas) fee: charged to the merchant at cost plus a per-chain margin. Merchants are shown one combined "Network Fee" figure. Who absorbs the fee is per-transfer, set by the "fee_deduction" field on withdrawals and payouts: - "from_amount" (the default): the recipient receives amount minus fees. - "from_balance": the recipient receives exactly amount; fees are debited on top of it. ## Authentication Server-to-server calls use HMAC-SHA256 request signing. Three headers: X-API-Key: xfp_key_... X-Timestamp: X-Signature: The signature is computed over a payload of four parts joined by newlines: timestamp + "\n" + METHOD + "\n" + path + "\n" + body - path includes the query string when present, e.g. /v1/invoices?status=paid - body is the empty string for requests without one (most GETs) - the key is your API secret, which is never transmitted - the timestamp must be within 30 seconds of server time, which stops replay Dashboard sessions use a JWT bearer token instead; API integrations should use HMAC. ## Webhooks Events are delivered as a signed POST with headers X-FintraPay-Event-Id, X-FintraPay-Event, X-FintraPay-Timestamp and X-FintraPay-Signature. The signature covers timestamp + "\n" + body — the same construction as request signing. Failed deliveries retry 7 times over roughly 36 hours (1m, 5m, 30m, 2h, 6h, 12h, 15h). Every attempt is queryable, and any delivery can be resent; a resend is re-signed with a current timestamp so it still passes a freshness check. Deduplicate on X-FintraPay-Event-Id — it is stable across retries and resends. ## API reference (version 1.0.0) Base URL: https://fintrapay.io/v1 OpenAPI 3.0 spec: https://fintrapay.io/openapi.json Human documentation: https://fintrapay.io/docs ### GET /balance — Get Balances Get custodial balances per token/chain. ### GET /deposit-api/deposits — List All Deposits Deposits across all of your users. ### GET /deposit-api/deposits/{id} — Get Deposit Get a single deposit. ### GET /deposit-api/users — List End Users List your end users. ### POST /deposit-api/users — Create End User Register one of your own users so they can be issued persistent deposit addresses. Parameters: - email (string, optional): Max 255 characters - external_user_id (string, required): Your identifier for the user; unique within your account, max 255 characters - label (string, optional): Max 255 characters - metadata (string, optional): Arbitrary JSON. Must be valid JSON ### GET /deposit-api/users/{ext_id} — Get End User Get a user with their addresses and balances. ### PATCH /deposit-api/users/{ext_id} — Update End User Update a user. A blocked or deactivated user is refused new deposit addresses. Parameters: - block_reason (string, optional): Recorded against the block - email (string, optional): Max 255 characters - is_active (boolean, optional): Deactivate without blocking - is_blocked (boolean, optional): Block the user - label (string, optional): Max 255 characters ### GET /deposit-api/users/{ext_id}/addresses — List Deposit Addresses Addresses issued to this user across every chain. ### POST /deposit-api/users/{ext_id}/addresses — Create Deposit Address Issue a persistent address on one chain. Calling it again for the same user and chain returns the address already issued rather than minting a second one. Parameters: - blockchain (string, required): Chain to issue on ### POST /deposit-api/users/{ext_id}/addresses/all — Create All Deposit Addresses Issue addresses on all seven chains at once. ### GET /deposit-api/users/{ext_id}/balances — List User Balances Per-token, per-chain balances for one user. ### GET /deposit-api/users/{ext_id}/deposits — List User Deposits Deposits for one user, filterable by token, chain and status. ### GET /earn/contracts — List Earn Contracts List your earn contracts. ### POST /earn/contracts — Create Earn Contract Lock stablecoins to earn daily interest. Parameters: - amount (string, required): Amount to lock - blockchain (string, required): Chain - currency (string, required): Token - duration_months (integer, required): Lock period: 1, 3, 6, or 12 months ### GET /earn/contracts/{id} — Get Earn Contract Get a single Earn contract, including accrued and withdrawn interest. ### POST /earn/contracts/{id}/break — Break Earn Contract End a contract before maturity. Returned principal is the deposit minus interest already withdrawn; undrawn interest is forfeited. ### GET /earn/contracts/{id}/interest-history — Earn Interest History Daily interest accrual entries for a contract. ### POST /earn/contracts/{id}/withdraw-interest — Withdraw Earn Interest Withdraw accrued interest. Minimum $10 USD equivalent. Interest is paid from the platform treasury wallet. Parameters: - amount (string, optional): Amount to withdraw. Omit to withdraw all accrued interest. ### GET /earn/rates — Get APY Rates Public endpoint — no auth required. Returns current APY rates for all durations. ### GET /earn/withdrawals — List Earn Withdrawals List every interest withdrawal you've requested, across all your earn contracts, with its current status. Interest withdrawals are paid from the treasury wallet by our team, not broadcast automatically — status stays "requested" until sent. ### POST /fees/estimate — Estimate Fees Quote the platform fee, network fee and resulting net amount before committing to a payout or withdrawal. Parameters: - amount (string, required): Gross amount - blockchain (string, required): Chain - currency (string, required): Token - fee_deduction (string, optional): "from_amount" (default) or "from_balance" - type (string, optional): payout or withdrawal ### GET /health — Health Check Public endpoint — no auth required. Returns service health status. ### GET /invoices — List Invoices List invoices with pagination and filters. Parameters: - blockchain (string, optional): Filter by blockchain - currency (string, optional): Filter by token - page (integer, optional): Page number (default: 1) - page_size (integer, optional): Items per page (default: 20, max: 100) - status (string, optional): Filter: pending, awaiting_selection, paid, confirmed, confirmed_overpaid, confirmed_underpaid, expired ### POST /invoices — Create Invoice Create a stablecoin invoice. Omit currency/blockchain to let the customer choose on the hosted checkout page. Parameters: - accepted_chains (array, optional): Limit chains customer can pick. Omit for all. - accepted_tokens (array, optional): Limit tokens customer can pick. Omit for all. - amount (string, required): Payment amount (e.g. "100.00") - blockchain (string, optional): Chain: tron, bsc, ethereum, solana, base, arbitrum, polygon. Omit to let customer choose. - cancel_url (string, optional): Redirect URL if payment expires - currency (string, optional): Token: USDT, USDC, DAI, FDUSD, TUSD, PYUSD. Omit to let customer choose. - expiry_minutes (integer, optional): Expiration in minutes (default: 60, max: 1440) - external_id (string, optional): Your internal order/reference ID - mode (string, optional): "custodial" (default) or "non_custodial" - success_url (string, optional): Redirect URL after payment confirmed ### GET /invoices/{id} — Get Invoice Get invoice by ID. ### POST /invoices/{id}/overpayment/accept — Accept Overpayment Keep a customer's surplus. It stays on your balance. No request body. ### POST /invoices/{id}/overpayment/refund — Refund Overpayment Return a customer's surplus. Your balance is debited immediately and the amount reserved while the refund is in flight. The customer receives the overage minus the network fee. No request body. ### GET /invoices/{id}/refunds — List Invoice Refunds Every refund issued against this invoice, including partials. ### POST /invoices/{id}/refunds — Create Refund Refund an invoice, in full or in part, back to the payer on the original chain and token. Parameters: - amount (string, required): Amount to refund; must not exceed the unrefunded remainder - reason (string, optional): Your internal reason ### GET /merchants/me — Get Profile Get your merchant profile. ### GET /merchants/me/api-keys — List API Keys List your API keys. ### POST /merchants/me/api-keys — Create API Key Create a new API key with its own settings. ### PATCH /merchants/me/settings — Update Settings Update webhook URL, wallet addresses, and other settings. Parameters: - wallet_bsc (string, optional): BSC withdrawal wallet - wallet_ethereum (string, optional): Ethereum withdrawal wallet - wallet_tron (string, optional): TRON withdrawal wallet - webhook_url (string, optional): Callback URL for payment notifications ### GET /merchants/me/wallets — List Wallets List your registered withdrawal wallets. ### POST /merchants/me/wallets — Add Wallet Register a withdrawal destination wallet for a chain. Parameters: - address (string, required): Wallet address; validated for that chain's format - blockchain (string, required): Chain: tron, bsc, ethereum, solana, base, arbitrum, polygon - label (string, optional): Your label for this wallet ### GET /merchants/me/webhook-deliveries — List Webhook Deliveries Every delivery attempt for your endpoint, newest first. Use this to reconcile events you may have missed. Parameters: - event (string, optional): Filter by event name, e.g. invoice.paid - page (integer, optional): Page number (default: 1) - page_size (integer, optional): Items per page (default: 20, max: 100) - status (string, optional): Filter: pending, retrying, delivered, failed, skipped ### GET /merchants/me/webhook-deliveries/{id} — Get Webhook Delivery One delivery attempt, including the request body and response code. ### POST /merchants/me/webhook-deliveries/{id}/resend — Resend Webhook Re-deliver a webhook. It is re-signed with a CURRENT timestamp, so it passes a receiver's freshness check. Rate limited to 10/min, 30s cooldown per delivery, 20 resends per delivery lifetime. ### GET /merchants/me/webhook-subscriptions — Get Webhook Subscriptions Which events you receive. Opt-out model: an event absent from this list is ENABLED. ### PUT /merchants/me/webhook-subscriptions — Update Webhook Subscriptions Enable or disable individual events. Parameters: - subscriptions (array, required): Array of {event, enabled}. ### GET /merchants/stats — Get Merchant Stats Dashboard stats: total invoices, paid invoices, total volume, pending payouts/withdrawals, active earn contracts. Parameters: - mode (string, optional): "custodial" or "non_custodial" — restricts invoice counts/volume to that mode. Omit for both modes combined. Payouts/withdrawals/earn counts are always custodial-only. ### GET /payment-links — List Payment Links List your payment links. ### POST /payment-links — Create Payment Link A reusable payment URL that never expires. Parameters: - amount (string, optional): Required when fixed_amount is true - fixed_amount (boolean, optional): Default true. When false the payer chooses an amount within min/max - max_amount (string, optional): Upper bound for flexible links (default 10000.00) - min_amount (string, optional): Lower bound for flexible links (default 1.00) - slug (string, required): Public URL segment; must be unique across all merchants - title (string, required): Shown on the checkout page ### GET /payment-links/{id} — Get Payment Link Get a link with its total_paid and total_payments counters. ### PATCH /payment-links/{id} — Update Payment Link Update a link. amount, min_amount and max_amount are validated the same way as on create, and min/max are checked against the values already stored. Parameters: - amount (string, optional): Must be a positive number - max_amount (string, optional): Must be positive and not fall below min_amount - min_amount (string, optional): Must be positive and not exceed max_amount - status (string, optional): active, paused or archived. A paused link stops accepting payments - title (string, optional): Display title ### GET /payouts — List Payouts List payouts with pagination. ### POST /payouts — Create Payout Send crypto to any external address. Parameters: - amount (string, required): Amount to send - blockchain (string, required): Chain (tron, bsc, etc.) - currency (string, required): Token (USDT, USDC, etc.) - fee_deduction (string, optional): "from_amount" (default) — recipient gets amount minus fees. "from_balance" — recipient gets exactly amount; fees debited on top. - reason (string, optional): payment, refund, reward, airdrop, salary, other - reference (string, optional): Your internal reference - to_address (string, required): Recipient wallet address ### POST /payouts/batch — Batch Payout Send crypto to multiple recipients in one call. Parameters: - blockchain (string, required): Chain for all recipients - currency (string, required): Token for all recipients - fee_deduction (string, optional): Applies to every recipient. "from_amount" (default) — each recipient gets amount minus the per-recipient fee (payout fee + network fee); a line not exceeding it is rejected. "from_balance" — each recipient gets exactly amount; the per-recipient fee is debited on top. batch.total_amount is the total debited: the sum of every payout's gross_amount. - recipients (array, required): Array of {to_address, amount, reference}. amount supports at most 8 decimal places. A validation failure returns 422 with one field error per bad recipient, keyed by array position, e.g. recipients[0].amount, recipients[2].to_address. ### GET /payouts/batches — List Payout Batches List batch payouts. ### GET /payouts/batches/{id} — Get Payout Batch Get a batch and its per-recipient items. ### GET /payouts/{id} — Get Payout Get a payout by ID. ### GET /refunds — List Refunds List refunds across all invoices. Response includes a summary object (refunded_amount, pending_count, completed_count) computed over every matching refund, not just the current page. Parameters: - blockchain (string, optional): Filter by blockchain - page (integer, optional): Page number - page_size (integer, optional): Items per page (max 100) - status (string, optional): pending, processed, completed, cancelled, failed ### GET /refunds/{id} — Get Refund Get a refund by ID. ### GET /subscription-plans — List Plans List your subscription plans. ### POST /subscription-plans — Create Plan A recurring billing plan. Parameters: - amount (string, required): Amount charged each interval - currency (string, required): Token - interval (string, required): day, week, month or year - interval_count (integer, optional): Number of intervals between charges (default 1) - name (string, required): Plan name ### GET /subscription-plans/{id} — Get Plan Get a plan by ID. ### PATCH /subscription-plans/{id} — Update Plan Update a plan's name, amount or status. ### GET /subscriptions — List Subscriptions List subscriptions, filterable by status and plan. ### POST /subscriptions — Create Subscription Subscribe a customer to a plan. Parameters: - customer_email (string, optional): Customer identifier - plan_id (string, required): Plan to subscribe to ### GET /subscriptions/{id} — Get Subscription Get a subscription and its invoice history. ### POST /subscriptions/{id}/cancel — Cancel Subscription Cancel a subscription. No further invoices are raised. ### POST /subscriptions/{id}/pause — Pause Subscription Pause billing without cancelling. ### POST /subscriptions/{id}/resume — Resume Subscription Resume a paused subscription. Billing anchors to the original billing day. ### GET /tickets — List Tickets List your support tickets. ### POST /tickets — Create Ticket Open a support ticket. Parameters: - category (string, optional): Ticket category - message (string, required): First message body - subject (string, required): Ticket subject ### GET /tickets/{id} — Get Ticket A ticket with its full message thread. ### POST /tickets/{id}/reply — Reply to Ticket Add a message to an existing ticket. Parameters: - message (string, required): Message body ### GET /transfers — List Transfers Transfers in both directions; each row carries a direction of in or out. ### POST /transfers — Create Internal Transfer Move custodial balance to another FintraPay merchant by email. Settles on our ledger with no on-chain transaction and no network fee. Requires a one-time code from /transfers/otp. Parameters: - amount (string, required): Amount to transfer - blockchain (string, required): Chain - currency (string, required): Token - note (string, optional): Free-text note shown to the recipient - otp (string, required): One-time code from /transfers/otp, bound to this transfer and single use - to_email (string, required): Recipient merchant email ### GET /transfers/lookup — Look Up Recipient Resolve a recipient email to a display name before sending. Parameters: - email (string, required): Recipient merchant email ### POST /transfers/otp — Request Transfer OTP Email a one-time confirmation code to the authenticated sender. ### GET /withdrawals — List Withdrawals List withdrawals with pagination. ### POST /withdrawals — Create Withdrawal Withdraw custodial balance. No flat fee — you pay the network fee only. Parameters: - amount (string, required): Amount to withdraw - blockchain (string, required): Chain - currency (string, required): Token - fee_deduction (string, optional): "from_amount" (default) — recipient gets amount minus fees. "from_balance" — recipient gets exactly amount; fees debited on top. - to_address (string, optional): Destination; falls back to your registered wallet for this chain ### GET /withdrawals/{id} — Get Withdrawal Get a withdrawal by ID. ## Notes for automated readers - Amounts are decimal strings, never floats. "100.00", not 100.0. - At most 8 decimal places on any amount. - Errors return a JSON object with "error" and "code". Validation failures are 422 and carry per-field messages; for arrays the field key includes the index, e.g. recipients[0].amount. - Idempotency: pass external_id on invoice creation to tie an invoice to your own order ID. - Official SDKs: Python, PHP, Node.js, Go, Java.