Mobula flags select tokens with isCashbackCoin = true in tokens_stats_real_time. These tokens reward traders with cashback on every swap. This guide shows how to filter a Pulse stream so only cashback-enabled tokens are returned — via both the REST endpoint and the WebSocket stream.
The is_cashback_coin filter is a token-level boolean. It works in asset mode only (assetMode: true). For a full list of asset-mode filters, see Filter Details.
The payload
The core idea: take your usual multi-view Pulse payload (bonding, bonded, new) and drop is_cashback_coin: { equals: true } into each view’s filters. You can narrow further with preBondingFactory / pool factory to keep only PumpFun (add letsbonk if you want Bonk launchpad too).
{
"assetMode": true,
"compressed": false,
"views": [
{
"name": "bonding",
"chainId": ["solana:solana"],
"limit": 50,
"model": "bonding",
"filters": {
"is_cashback_coin": { "equals": true },
"preBondingFactory": { "in": ["pumpfun", "letsbonk"] }
}
},
{
"name": "bonded",
"chainId": ["solana:solana"],
"limit": 50,
"model": "bonded",
"filters": {
"is_cashback_coin": { "equals": true },
"preBondingFactory": { "in": ["pumpfun", "letsbonk"] }
}
},
{
"name": "new",
"chainId": ["solana:solana"],
"limit": 50,
"model": "new",
"filters": {
"is_cashback_coin": { "equals": true },
"preBondingFactory": { "in": ["pumpfun", "letsbonk"] }
}
}
]
}
preBondingFactory identifies the launchpad a token originated from (e.g. pumpfun, letsbonk, moonshot-evm). If you only care about PumpFun, use { "in": ["pumpfun"] }.
REST (one-shot snapshot)
POST /api/2/pulse returns a single snapshot per view.
Base endpoint
cURL
curl -X POST https://api.mobula.io/api/2/pulse \
-H "Authorization: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"assetMode": true,
"compressed": false,
"views": [
{
"name": "bonding",
"chainId": ["solana:solana"],
"limit": 50,
"model": "bonding",
"filters": {
"is_cashback_coin": { "equals": true },
"preBondingFactory": { "in": ["pumpfun", "letsbonk"] }
}
},
{
"name": "bonded",
"chainId": ["solana:solana"],
"limit": 50,
"model": "bonded",
"filters": {
"is_cashback_coin": { "equals": true },
"preBondingFactory": { "in": ["pumpfun", "letsbonk"] }
}
},
{
"name": "new",
"chainId": ["solana:solana"],
"limit": 50,
"model": "new",
"filters": {
"is_cashback_coin": { "equals": true },
"preBondingFactory": { "in": ["pumpfun", "letsbonk"] }
}
}
]
}'
TypeScript (fetch)
const payload = {
assetMode: true,
compressed: false,
views: [
{
name: 'bonding',
chainId: ['solana:solana'],
limit: 50,
model: 'bonding',
filters: {
is_cashback_coin: { equals: true },
preBondingFactory: { in: ['pumpfun', 'letsbonk'] },
},
},
{
name: 'bonded',
chainId: ['solana:solana'],
limit: 50,
model: 'bonded',
filters: {
is_cashback_coin: { equals: true },
preBondingFactory: { in: ['pumpfun', 'letsbonk'] },
},
},
{
name: 'new',
chainId: ['solana:solana'],
limit: 50,
model: 'new',
filters: {
is_cashback_coin: { equals: true },
preBondingFactory: { in: ['pumpfun', 'letsbonk'] },
},
},
],
};
const res = await fetch('https://api.mobula.io/api/2/pulse', {
method: 'POST',
headers: {
Authorization: process.env.MOBULA_API_KEY!,
'Content-Type': 'application/json',
},
body: JSON.stringify(payload),
});
const { data } = await res.json();
// data.bonding, data.bonded, data.new — each is an array of cashback-enabled tokens
WebSocket (live stream)
Same payload, streamed over Pulse V2 WSS. New cashback tokens and updates are pushed continuously.
Using the Mobula SDK
import { MobulaClient } from '@mobula/sdk';
const client = new MobulaClient({
restUrl: 'https://pulse-v2-api.mobula.io',
apiKey: process.env.MOBULA_API_KEY!,
});
const subscriptionId = client.streams.subscribe(
'pulse-v2',
{
assetMode: true,
compressed: false,
views: [
{
name: 'bonding',
chainId: ['solana:solana'],
limit: 50,
model: 'bonding',
filters: {
is_cashback_coin: { equals: true },
preBondingFactory: { in: ['pumpfun', 'letsbonk'] },
},
},
{
name: 'bonded',
chainId: ['solana:solana'],
limit: 50,
model: 'bonded',
filters: {
is_cashback_coin: { equals: true },
preBondingFactory: { in: ['pumpfun', 'letsbonk'] },
},
},
{
name: 'new',
chainId: ['solana:solana'],
limit: 50,
model: 'new',
filters: {
is_cashback_coin: { equals: true },
preBondingFactory: { in: ['pumpfun', 'letsbonk'] },
},
},
],
},
(msg) => {
// msg.view tells you which bucket (bonding | bonded | new) the update belongs to
console.log(msg.view, msg.data);
},
);
Raw WebSocket
If you’re not using the SDK, send the same object as the subscription payload over the Pulse V2 WSS connection (see Pulse WebSocket Integration for the handshake details).
Verifying the filter is applied
Each token in the response exposes isCashbackCoin both at the root and inside token:
{
"address": "...",
"symbol": "...",
"isCashbackCoin": true,
"isMayhemMode": false,
"isAgentMode": false,
"token": {
"isCashbackCoin": true,
"...": "..."
}
}
If you’re seeing tokens with isCashbackCoin: false or null, double-check that assetMode is true — the flag is only filtered in asset mode.
is_mayhem_mode — Mayhem program tokens
is_agent_mode — Agent mode tokens
preBondingFactory / pools.factory — restrict to a specific launchpad
bonded — only bonded or only pre-bonded tokens
min_socials, pattern, includeKeywords — additional narrowing
See the full list in Filter Details.