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
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"
}'| Field | Type | Notes |
|---|---|---|
amount | number | USD, $10,000 maximum. $0.01 minimum, $1 minimum if is_private is true. |
recipient_type | string | email, username, twitter, discord, github, or telegram. |
recipient_identifier | string | The email address, Loofta username, or handle, matching recipient_type. |
sender_wallet | string, optional | Your 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_source | string, optional | Fund from another chain instead of signing a Solana transaction: gram_ton or usdc_base. 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.gram_ton pays with native TON coin (labeled GRAMin most bridge APIs, TON's original pre-launch name) rather than a USDT jetton, and never has Loofta's cross-chain fee applied. |
refund_wallet | string, optional | Your address on the funding_source chain, used to refund you if the deposit can't complete. Required when funding_source is set. |
message | string, optional | Shown to the recipient on their claim page. 500 characters max. |
is_private | boolean, optional | Defaults 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.com/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 GRAM (native TON)/USDC to on the chain you actually hold funds on:
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": "gram_ton",
"refund_wallet": "UQYourTonAddress..."
}'{
"payment_id": "b3f1...e02a",
"short_id": "aB3xK9pQ",
"claim_link": "https://pay.loofta.com/c/aB3xK9pQ",
"is_private": false,
"funding_source": "gram_ton",
"deposit_address": "UQC9f2c...4a1b",
"deposit_address_raw": "0:bd7f6c...",
"deposit_memo": null,
"deposit_amount": "18.652031",
"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.
gram_ton pays with native TON coin rather than a USDT jetton — a plain value transfer, so there's no jetton-wallet notification step that can fail from insufficient gas the way a jetton transfer's can. It's also fee-free: Loofta never adds its own cross-chain fee on top for this route.
Want your recipient landing on your own branded page instead of pay.loofta.com? . 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.