Pagination and data handling
Use the interactive reference to inspect the response and try a single page. This guide shows how to continue through results safely.
Find your partner’s presales
Section titled “Find your partner’s presales”Set partner_id to the on-chain partner object ID, not your API-key account name or wallet address. Filtering happens before sorting and pagination. A partner with no matching presales returns 200 with an empty array and a null cursor.
This server-side JavaScript example follows every page of live presales. Set BLAST_PARTNER_KEY and BLAST_PARTNER_ID in your backend environment.
const key = process.env.BLAST_PARTNER_KEY;const partnerId = process.env.BLAST_PARTNER_ID;if (!key || !/^0x[0-9a-f]{64}$/.test(partnerId ?? '')) { throw new Error('Configure a partner key and canonical partner object ID.');}
const query = new URLSearchParams({ partner_id: partnerId, status: 'live', sort: 'ending', limit: '50',});const sales = new Map();const visited = new Set();
for (;;) { const response = await fetch( `https://www.blast.fun/api/v1/presales?${query}`, { headers: { 'X-Blast-Partner-Key': key }, signal: AbortSignal.timeout(15000) }, ); if (!response.ok) { // Honor Retry-After for 429/503 in your job scheduler. Do not loop here. throw new Error(`Blast HTTP ${response.status}; retry-after=${response.headers.get('retry-after')}`); } const page = await response.json(); for (const sale of page.presales) sales.set(sale.presale_id, sale); if (page.next_cursor === null) break; if (visited.has(page.next_cursor)) throw new Error('Repeated pagination cursor.'); visited.add(page.next_cursor); query.set('cursor', page.next_cursor);}
console.log([...sales.values()]);Keep status, sort, partner_id, verified_team, and audited unchanged between pages. Treat cursor tokens as opaque. Results can change as new activity is indexed; deduplicate by ID when collecting multiple pages. Paginating is not a frozen snapshot of the entire dataset.
Know which cursor to use
Section titled “Know which cursor to use”| Endpoint | Read from response | Send in next request | Stop when |
|---|---|---|---|
| Presales | next_cursor |
cursor |
Cursor is null |
| Discovery | section.data.nextCursor |
cursor, same view |
Cursor is null or section is empty |
| Search | Group’s section.data.nextCursor |
cursor, same group and q |
Cursor is null or section is empty |
| Holders | next_cursor |
cursor, same coin and view |
Cursor is null; incomplete data is unavailable |
| Launch activity | next_cursor |
cursor, same launch and view |
Cursor is null |
| Pool candles | Oldest bucket_start |
to |
Candle array is empty |
| Pool trades | Last row’s cursor |
before |
Trade array is empty or archive boundary is reached |
Preserve precision and units
Section titled “Preserve precision and units”Amounts ending in _atoms, market reserves, and market trade volumes are decimal strings in the coin’s smallest units. Use BigInt for integer arithmetic and a decimal library for prices. Converting large balances to JavaScript Number loses precision.
- Social price history: prices are USD per whole token. Points are
[timestamp_ms, decimal_price_string]pairs. - Market pool and candle prices: prices are quote atoms per meme atom. Convert to quote coins per whole token by multiplying by
10^(meme_decimals − quote_decimals)using decimal arithmetic. - Basis points: 10,000 means 100%. Check the field schema: some endpoints use JSON integers and others decimal strings.
- Time: timestamps labeled
_msorMsare Unix milliseconds. A duration is not a timestamp. Specific fields such aspublish_timeuse Unix seconds; their schemas say so.
Empty, missing, and stale are different
Section titled “Empty, missing, and stale are different”[] means a successful read with no matching items. null means the particular fact is unavailable or not applicable; do not silently turn it into zero. An omitted optional field is different from a required field whose value is null.
Discovery and search expose available, stale, empty, and unavailable sections. Only available and stale contain data. A search can return 200 while one group is unavailable. An incomplete holder snapshot has null facts, not zero holders.
Inspect as_of or provenance before presenting data as current. Preserve the indexed timestamp if you cache a response, and follow the returned cache policy. See rate limits and errors for retry behavior.