Loofta Paypay
Loofta

For you

  • Send
  • Receive
  • History
  • Settings

Partners

  • Checkout
  • Partners
  • Payment links
  • Developer docs

Learn

  • How Loofta works
  • Send crypto privately
  • USDC to Naira rate
  • Dollar to Naira today
  • Loofta vs PayPal
  • Blog

Company

  • About
  • Careers
  • Terms of Service
  • Privacy Policy

Socials & Docs

  • Medium
  • Twitter
  • Telegram
  • Docs

Ecosystem

  • MagicBlock
  • Blink.cash
USD

© 2026 Loofta. All rights reserved.

    Developer

    Getting started

    Setup

    Receive payments

    Send payments

    Send payments

    Pay anyone by identity, no wallet address needed on either side:

    • Community members — Discord or Telegram handle.
    • Contributors — GitHub username or email.
    • Creators — X handle. TikTok and Instagram are coming.
    • Collaborators, freelancers, bounty winners — email or username.
    • One or many — pay one person with this endpoint, or batch up to 10 recipients in a single signature with multi-send.

    Recipients don't need a wallet ready to go either. They claim straight to a wallet Loofta sets up for them on the spot, or, in Nigeria, straight to a bank account instead.

    POST /payouts pays a recipient — by email, username, or social handle — from the API key owner's own account. The counterpart to : that one gets you paid, this one pays someone else. Self-custody — it returns an unsigned transaction, you sign it with your own wallet. Loofta never holds or moves your funds on your behalf.

    Need a specific SPL token, a recurring payout schedule, funds released only when a condition is met, or a custom integration into your own systems? Message us on Telegram or email us and we'll build it with you.

    Try it — pay someone now

    Live (mainnet) — this sends a real, small payout from your own account. Pay now calls POST /payouts with your API key; on Solana it signs the returned transaction with your own Loofta wallet right here and broadcasts it, the same round trip a real integration makes. If you leave it unsettled — never signed, or never funded at the deposit address — it auto-expires after 4 hours.

    Signs a Solana transaction with your own Loofta wallet, right here.

    Don't have a key yet? .

    Request

    POST /payouts
    curl -X POST https://api.loofta.xyz/payouts \
      -H "Authorization: Bearer lft_live_..." \
      -H "Content-Type: application/json" \
      -d '{
        "amount": 25,
        "recipient_type": "email",
        "recipient_identifier": "alice@example.com",
        "sender_wallet": "5dCT...BKuq",
        "message": "August payout"
      }'
    FieldTypeNotes
    amountnumberUSD, $10,000 maximum. $1 minimum, $5 minimum if is_private is true.
    recipient_typestringemail, username, twitter, discord, github, or telegram.
    recipient_identifierstringThe email address, Loofta username, or handle, matching recipient_type.
    sender_walletstring, optionalYour own Solana wallet's public key — pays gas and signs the returned transaction. Loofta never touches it. Omit if you're paying with funding_source instead.
    funding_sourcestring, optionalFund from another chain instead of signing a Solana transaction: usdt_ton, usdc_base, or usdc_stellar. Pass this instead of sender_wallet — the response gives you a deposit address and the exact amount to send there for an exact-output delivery. Requires refund_wallet.
    refund_walletstring, optionalYour address on the funding_source chain, used to refund you if the deposit can't complete. Required when funding_source is set.
    messagestring, optionalShown to the recipient on their claim page. 500 characters max.
    is_privateboolean, optionalDefaults to false. Pass true to shield the amount and your wallet on-chain — a MagicBlock private transfer, ~10 bps + $0.20 flat gas on top of amount.

    A payout that never gets funded auto-expires — unsigned_transaction never signed and broadcast expires 4 hours after creation; nothing ever sent to a deposit_address expires whenever that deposit address's own bridge quote does (often a few days, never less than 4 hours), since the claim shouldn't die before the address stops being watched. Once expired, claim_link no longer accepts payment. A payout that has already been funded is unaffected, however long the recipient takes to claim it.

    Response

    {
      "payment_id": "b3f1...e02a",
      "short_id": "aB3xK9pQ",
      "claim_link": "https://pay.loofta.xyz/c/aB3xK9pQ",
      "unsigned_transaction": "AQAAAAAAAAAAAAAAAAAAAAAA...",
      "transaction_version": "legacy",
      "send_to": "base",
      "is_private": false
    }

    unsigned_transaction is a base64-encoded, unsigned Solana transaction — transaction_version tells you whether to deserialize it as a legacy Transaction or a VersionedTransaction (private transfers can come back as either; public ones are always legacy). send_to tells you which RPC to broadcast the signed transaction to — "base" is regular Solana; a private transfer can come back as "ephemeral", MagicBlock's own rollup RPC, instead.

    Sign and broadcast

    This is the one step Loofta can't do for you — sender_wallet is your own wallet, so only you can authorize spending from it. Deserialize, sign with that wallet's keypair, and send it to the RPC send_to names:

    import { Connection, Transaction, VersionedTransaction, Keypair } from "@solana/web3.js";
    
    const rpcUrl = send_to === "ephemeral"
      ? "https://mainnet-tee.magicblock.app"
      : "https://api.mainnet-beta.solana.com";
    const connection = new Connection(rpcUrl);
    const senderKeypair = Keypair.fromSecretKey(/* your own key, never sent to Loofta */);
    
    const raw = Buffer.from(unsigned_transaction, "base64");
    const tx = transaction_version === "v0"
      ? VersionedTransaction.deserialize(raw)
      : Transaction.from(raw);
    
    tx.sign(senderKeypair); // VersionedTransaction: tx.sign([senderKeypair])
    const signature = await connection.sendRawTransaction(tx.serialize());

    The recipient sees the payout waiting for them at claim_link the moment your transaction lands — same claim/burner mechanics as every other Loofta payment, so an unregistered recipient claims by signing in with the email or handle you sent it to.

    Funding from another chain

    Pass funding_source instead of sender_wallet to skip the Solana transaction entirely — you'll get a deposit address to send USDT/USDC to on the chain you actually hold funds on:

    POST /payouts
    curl -X POST https://api.loofta.xyz/payouts \
      -H "Authorization: Bearer lft_live_..." \
      -H "Content-Type: application/json" \
      -d '{
        "amount": 25,
        "recipient_type": "email",
        "recipient_identifier": "alice@example.com",
        "funding_source": "usdc_base",
        "refund_wallet": "0xYourBaseAddress..."
      }'
    {
      "payment_id": "b3f1...e02a",
      "short_id": "aB3xK9pQ",
      "claim_link": "https://pay.loofta.xyz/c/aB3xK9pQ",
      "is_private": false,
      "funding_source": "usdc_base",
      "deposit_address": "0x9f2c...4a1b",
      "deposit_memo": null,
      "deposit_amount": "25.081234",
      "deposit_deadline": "2026-09-07T12:34:56.000Z"
    }

    Send exactly deposit_amount of the funding_source token to deposit_address (include deposit_memo if present) before deposit_deadline. Alice sees the payout at claim_link once the deposit is confirmed and swept — there's nothing left for you to sign or broadcast.

    deposit_note (only present for usdt_ton): every TON deposit address is brand new and holds zero TON. Most wallets attach enough gas automatically when you use their normal send flow, but a jetton transfer sent with too little forward gas can land on-chain and still never register as a deposit — the confirmed failure mode is a gas-starved notification message, not a lost payment, but it needs manual recovery either way. Read this field and pass it through to whoever's actually sending the funds.

    Want your recipient landing on your own branded page instead of pay.loofta.xyz? . It's set up on-demand, contact us to turn it on.

    Building with an AI coding agent? Grab the copyable — it covers this endpoint too.