Loading home
Launch a token to any handle
Creator fees route as SOL. This line only sizes the home skeleton.
Marketplace row placeholder name
12.4k volume
Marketplace row placeholder name
12.4k volume
Marketplace row placeholder name
12.4k volume
Launch from a bot. No API key and no login. A launch defaults to pump.fun. On a SOL pair, pass venue "launchlab" when GET /api/v1/launchpad lists it. Any other pair stays on pump.fun. The Paygram routing wallet is the on-chain deployer, so pump.fun lists Paygram as the creator; your wallet signs and repays the create cost inside the same transaction. The handle is who receives the fees — pin yours on every launch while other people pick the ticker. 80% goes to that Telegram, X, GitHub, or Fomo handle, 20% buys and burns $PAYGRAM.
handle is the fee destination. It does not have to be the person who picked the ticker, and it is not the wallet that signs. Set it to your account on every call. Each coin is separate. The 80% for that @ sits in one vault. You claim it on /claim by signing in as that Telegram, X, or GitHub account. Fomo has no sign-in: the 80% is sent to the Solana address frozen at launch once at least 0.001 SOL is waiting, at most every 6 hours. This API does not send the payout.
Your bot signs. Keep one funded keypair. When someone sends a ticker, a name, and an image URL, prepare with your fixed handle, sign, and submit. They never need a wallet. The keypair must hold at least 0.025 SOL for the create, plus devBuy if you set one. The image has to be a public https URL — a file upload and a Telegram file id are refused.
const HANDLE = "yourname";
const NETWORK = "telegram";
const prepared = await fetch("https://usepaygram.com/api/v1/launches", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({
wallet: keypair.publicKey.toBase58(),
handle: HANDLE,
network: NETWORK,
tokenSymbol: "TICKER",
tokenName: "Name they picked",
image: "https://example.com/image.png",
quote: "sol",
}),
}).then((res) => res.json());Then sign and submit that transaction the same way as below. Show https://pump.fun/coin/{mint} and https://usepaygram.com/token/{mint}.
They sign. Prepare with wallet set to their pubkey and handle still set to yours. Send them unsignedTransaction. They pay and sign. Fees still route to your handle.
Or send a link that opens the form with your @ filled in: https://usepaygram.com/launch?handle=yourname&network=telegram. network is telegram, x, github, or fomo. Optional ticker, name, buy, and description. The person can still change the @ before they sign. Their wallet pays the create fee — Paygram routing never does. When the destination has to stay yours, set handle in the API call and do not hand them the form.
Read the vault with no key. Telegram, X, GitHub, and Fomo are separate vaults, even when the @ is the same. routes lists every coin on that destination. pendingSol is the 80% not claimed yet, on SOL pairs. Claim at https://usepaygram.com/claim?handle=yourname, and add &network=x, &network=github, or &network=fomo for the others. Fomo fees are paid to the frozen address, so that claim link does not ask for a sign-in.
GET /api/handles/yourname?network=telegram
{
"handle": "yourname",
"network": "telegram",
"pendingSol": 1.2,
"receivedSol": 4.0,
"optedOut": false,
"bound": false,
"routes": [
{ "mint": "…", "tokenSymbol": "TICKER", "pendingSol": 0.4 }
]
}30 prepares per minute per IP. Queue the invites. The handle must already exist and must not have opted out. A GitHub organization is refused. A Fomo handle must be on the leaderboard with a Solana address — that address is frozen, and the 80% is sent to it once at least 0.001 SOL is waiting, at most every 6 hours. If submit comes back after the blockhash expires, prepare again.
Register a place of exchange (Elon on X, Robert on Telegram, …), with photo, banner, and socials, then launch a place token and child tokens for that market. To launch a marketplace coin paired with $PAYGRAM (or open a parent pump coin you already have) and launch child custom pairs, go to /ecosystems/launch (every marketplace is listed at /ecosystems) — the parent keeps 80/20, and each child's creator fees go to the child handle, paid in the parent token. Paygram stays the rail — create, 80/20 on the place token, claim — while child tokens keep their own routing and list on the board. This is not an order book: tokens launch and distribute like a StonkBlend / Grand Exchange gold board, not matching offers.
Same auth as launches: no API key. Send the deployer wallet. The wallet is recorded as owner; it does not have to own the social handle.
POST /api/v1/marketplaces
Content-Type: application/json
{
"wallet": "<deployer pubkey>",
"name": "Elon Exchange",
"slug": "elon-exchange",
"handle": "elonmusk",
"network": "x",
"quote": "sol",
"description": "optional short note",
"image": "https://example.com/photo.png",
"banner": "https://example.com/banner.png",
"website": "https://example.com",
"twitter": "elonmusk",
"telegram": "https://t.me/…"
}{
"marketplace": {
"id": "…",
"name": "Elon Exchange",
"slug": "elon-exchange",
"handle": "elonmusk",
"network": "x",
"defaultQuote": "sol",
"description": "optional short note",
"image": "https://example.com/photo.png",
"banner": "https://example.com/banner.png",
"primaryMint": null,
"childFeeBps": 0,
"ownerWallet": "…",
"createdAt": 1710000000000
}
}Then prepare a launch with marketplaceId set to that id or slug. The fee destination handle and quote come from your request — any public network handle, any quote Paygram already resolves (SOL, a pump pair, or a basket on SOL). If you omit quote and the marketplace has a default, that default is used. An unknown quote is rejected.
const prepared = await fetch("https://usepaygram.com/api/v1/launches", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({
wallet: keypair.publicKey.toBase58(),
marketplaceId: "elon-exchange",
handle: "durov",
network: "telegram",
tokenSymbol: "TICKER",
image: "https://example.com/image.png",
quote: "amznx",
}),
}).then((res) => res.json());
// then sign + submit as usualRead the market and its tokens with no key: GET /api/v1/marketplaces/{idOrSlug}.
GET /api/v1/marketplaces/elon-exchange
{
"marketplace": { "id": "…", "slug": "elon-exchange", "handle": "elonmusk", "network": "x", "primaryMint": "…", "childFeeBps": 0 },
"primary": { "mint": "…", "tokenSymbol": "ELON", "marketplacePrimary": true },
"children": [
{ "mint": "…", "tokenSymbol": "TICKER", "marketplaceFeeBps": null, "marketplaceId": "…" }
],
"tokens": [ "…" ]
}A parent pump.fun coin with children quoted in it (pump.fun Custom Pairs, depth up to 2). In the app, /ecosystems/launch has three tabs — ?tab=new (new token), ?tab=paygram (already on Paygram) and ?tab=migrate (fee switch, then open), the last two taking &mint=. Every marketplace is listed at /ecosystems. Over the API it is two calls: launch a new one, or open one on a coin you have.
Launch a marketplace. A new coin paired with $PAYGRAM (depth 1), created and paid by the deployer wallet — the routing vault never pays. Prepare with POST /api/v1/ecosystems/launch, sign devBuy.unsignedTx, then send it to POST /api/v1/launches/submit with id = route.id. Once the create lands, the coin is registered as the ecosystem at /ecosystems/{slug} (a slug taken in the meantime gets a short mint suffix). Its fees are paid in $PAYGRAM: 80% to the handle, the 20% burned as is. Prove the wallet with a Privy session, or sign the message below with walletSignature and walletSignatureIssuedAt (same rules as a child signature). Up to 3 marketplace launches per wallet per day. Its children are depth 2 (SOL → $PAYGRAM → parent → child): they open once Paygram has created the ecosystem's lookup table; childrenOpen on the ecosystem says when.
POST /api/v1/ecosystems/launch
Content-Type: application/json
Authorization: Bearer <Privy session> (or walletSignature below)
{
"wallet": "<deployer pubkey>",
"handle": "elonmusk",
"network": "x",
"tokenSymbol": "ELON",
"tokenName": "Elon Market",
"image": "https://example.com/photo.png",
"marketplace": {
"name": "Elon Market",
"slug": "elon-market",
"description": "optional short note",
"banner": "https://example.com/banner.png",
"website": "https://example.com",
"twitter": "elonmusk",
"telegram": null
}
}
→ 201 { "route": { "id": "…", "mint": "…", "quoteSymbol": "PAYGRAM", "status": "minting" },
"devBuy": { "status": "needs_signature", "unsignedTx": "<base64 versioned tx>" },
"ecosystem": null }Paygram marketplace launch wallet: <deployer pubkey> slug: <slug, lowercase> ticker: <TICKER, uppercase> issued: <unix ms>
Open an ecosystem on a coin you already have. It must route its creator fees through Paygram — a Paygram launch, or an external coin moved with the fee switch (/fee-switch) whose pump.fun fee-sharing admin is revoked. Check with GET /api/v1/ecosystems/eligibility?mint=; open one with POST /api/v1/ecosystems (parentMint, slug, wallet = the coin's fee owner on Paygram). pump.fun cannot change an existing coin's pair, so it keeps its own (usually SOL — quoteSymbol in the eligibility answer, parentQuoteSymbol on the ecosystem): a depth-0 parent whose fees stay 80/20 in that pair, the 20% buying and burning $PAYGRAM. Its children are depth 1 and need no per-ecosystem lookup table.
Launch a child with the normal launch request and quote: "pump:<parentMint>". The child's creator fees go 100% to its own handle and/or holders, paid in the parent token; Paygram takes no cut from children and the parent keeps 80/20. Read the tree with GET /api/v1/ecosystems/{slug} and rankings with GET /api/v1/ecosystems/leaderboard?kind=children|ecosystems. Children launched outside Paygram are indexed too.
A child launch must prove the paying wallet: send a Privy session as Authorization: Bearer <token>, or sign this message with the wallet (signMessage, ed25519) and send walletSignature (base58 or base64) and walletSignatureIssuedAt (the same ms timestamp). A signature works once, for 10 minutes, and is only used up by a launch that passes every other check. Sign the ticker as launched: uppercase, without $ ($kid signs as KID). Each wallet can launch a limited number of children per ecosystem per day. Other launches need neither: their Authorization header is ignored.
Paygram child launch wallet: <deployer pubkey> parent: <parentMint> ticker: <TICKER, uppercase> issued: <unix ms>
Send the ticker, handle, quote, and deployer wallet. The response is an unsigned transaction. POST /api/v1/launches. The coin is not created yet. In live mode the status is needs_signature and unsignedTransaction is a versioned transaction the deployer must sign. Sign and submit before the blockhash expires (about a minute). If it expires, prepare again.
POST /api/v1/launches
Content-Type: application/json
{
"wallet": "<deployer pubkey>",
"handle": "durov",
"network": "x",
"tokenSymbol": "TICKER",
"tokenName": "Ticker",
"image": "https://example.com/image.png",
"description": "optional note",
"quote": "amznx"
}{
"id": "…",
"mint": "…",
"status": "needs_signature",
"unsignedTransaction": "<base64 versioned tx>",
"signature": null,
"route": { "feeRecipient": "…", "handle": "x:durov", "quoteSymbol": "AMZNx" }
}Do not send mint, feeRecipient, treasuryAddress, or feeShares. Paygram assigns those. On pump.fun the Paygram routing wallet deploys the coin: it is the fee payer and creator, and the first transfer in the transaction repays it the exact create rent and network fee from wallet. Your wallet is not the creator-fee wallet.
| Field | Required | Notes |
|---|---|---|
| wallet | yes | Launch wallet pubkey. It signs, repays the create cost, pays any dev buy, and keeps the dev-buy tokens. |
| handle | yes | Public @ that receives the 80%. Must already exist. Pin yours on every call when other people launch through your bot. Not the deployer. |
| network | no | telegram (default), x, github, or fomo. Each @ is its own destination. GitHub organizations are refused. A Fomo handle must be on the leaderboard with a Solana address; that address is frozen at launch. |
| tokenSymbol | yes | 2–10 characters, A–Z and 0–9. A leading $ is stripped. |
| tokenName | no | Up to 32 characters. Defaults to the handle name. |
| image | no | Public https URL only, up to 2000 characters. A file upload is not accepted. |
| description | no | Optional note. Paygram appends the fee-routing line. |
| quote | no | sol, a pump pair symbol (amznx, xmr), or that asset's mint. Default sol. An ecosystem child uses pump:<parentMint>. $PAYGRAM is only a pair through POST /api/v1/ecosystems/launch. |
| basket | no | SOL launches only. Up to 5 Solana xStock ids or mints (including ones pump does not list as a pair), or DOGE / PEPE / TAO. The 80% buys them in equal parts. |
| venue | no | pump (default) or launchlab. LaunchLab is a SOL pair only, and only when GET /api/v1/launchpad lists it. Any other pair rejects launchlab. |
| devBuy | no | SOL to buy in the same transaction. SOL pairs only. Max 10,000. |
| marketplaceId | no | Marketplace id or slug. Attributes this launch to that market. Fee handle and quote still come from this request. |
Your wallet signs that exact transaction. The mint key and the Paygram routing wallet have already signed. Deserialize unsignedTransaction, sign it with the wallet key, then POST the same bytes. Do not rebuild the transaction — the other signatures are already inside it, and a different message is rejected.
import { Keypair, VersionedTransaction } from "@solana/web3.js";
const prepared = await fetch("https://usepaygram.com/api/v1/launches", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({
wallet: keypair.publicKey.toBase58(),
handle: "durov",
network: "x",
tokenSymbol: "TICKER",
image: "https://example.com/image.png",
quote: "sol",
devBuy: 0.1,
}),
}).then((res) => res.json());
const tx = VersionedTransaction.deserialize(
Buffer.from(prepared.unsignedTransaction, "base64"),
);
tx.sign([keypair]); // mint key + Paygram routing wallet already signed — do not rebuild the tx
const submitted = await fetch("https://usepaygram.com/api/v1/launches/submit", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({
id: prepared.id,
signedTransaction: Buffer.from(tx.serialize()).toString("base64"),
}),
}).then((res) => res.json());Send the signed transaction back. The coin is live once it confirms. POST /api/v1/launches/submit
POST /api/v1/launches/submit
Content-Type: application/json
{
"id": "<id from prepare>",
"signedTransaction": "<same tx, base64, deployer signature added>"
}A successful submit returns status: "active" and the landing signature. Sending the same id again after it is active returns that launch. If confirmation is still pending, wait a few seconds and submit the same signed transaction again.
From mint, the coin is at https://pump.fun/coin/{mint} and https://usepaygram.com/token/{mint}.
GET /api/routes/{id} needs no key. buybacks are the 20% already spent on $PAYGRAM. payouts are what was sent to the handle. On a SOL pair, route.pendingSol is the 80% still waiting to be claimed. On any other pair the handle's 80% stays in that quote asset; payout parts name the asset. The handle owner claims on /claim — this API does not send the payout.
GET /api/routes/{id}
{
"route": {
"mint": "…",
"status": "active",
"receivedSol": 0.12,
"pendingSol": 0.096,
"paidSol": 0,
"quoteSymbol": null
},
"buybacks": [{ "sol": 0.024, "sig": "…", "ts": 1710000000000 }],
"payouts": [{ "handle": "x:durov", "sol": 0, "parts": [], "sig": null, "ts": 1710000000000 }]
}quote accepts sol, a symbol below, or the mint address. On any other pair the handle's 80% stays in that asset. A dev buy is refused on those pairs — those launches open with no buy. SpaceX on pump is SPCX, not the Backed SPCXx mint.
Building a terminal or bot? See the public API (read, quote, unsigned buy/sell/launch, OpenAPI spec).
30 prepares and 60 submits per minute per IP. Over the limit the status is 429. Invalid JSON is 400. An unknown launch id is 404. Everything else rejected at prepare or submit is 422, with error set.
wallet.status: "simulated" and no transaction. Production returns needs_signature.