TypeScript SDK
@pump-fun/api is a typed TypeScript client for https://api.pump.fun/v1. It has no runtime dependencies, uses the global fetch (Node 20 or newer), ships ESM and CommonJS, and types every route from the same OpenAPI document this site serves. It is MIT-licensed.
Install
Section titled “Install”pnpm add @pump-fun/api# or: npm install @pump-fun/apiFirst call
Section titled “First call”import { PumpApi, PumpApiError } from '@pump-fun/api';
const api = new PumpApi({ apiKey: process.env.PUMP_API_KEY! });
const { data: user, rateLimit } = await api.profiles.getUser({ id: '<wallet or user id>' });console.log(user.username, rateLimit?.remaining);Every route method takes one argument: path parameters at the top level, query for query parameters and body for JSON bodies. A second, optional argument carries per-call options (signal, timeoutMs, maxRetries, headers). The result is an object with these fields:
| Field | Type | Meaning |
|---|---|---|
data |
typed per route | The parsed response body. |
status |
number |
HTTP status code. |
headers |
Headers |
The raw response headers. |
requestId |
string | null |
X-Request-Id; quote it in support requests. |
apiKeyId |
string | null |
x-pump-api-key-id, the opaque id of the key that made the call. |
rateLimit |
{ limit, remaining, reset, resetAt } |
Parsed from the X-RateLimit-* headers, or null when absent. See Limits. |
deprecation |
{ announced, sunset, successor, docs, raw } |
Parsed from the Deprecation, Sunset and Link headers when the route is deprecated; otherwise null. |
Options
Section titled “Options”const api = new PumpApi({ apiKey: process.env.PUMP_API_KEY!, // required, pf_live_... baseUrl: 'https://api.pump.fun/v1', // the default maxRetries: 2, // retries after 429 / 5xx / connection failures; 0 disables maxRetryDelayMs: 30_000, // a longer Retry-After throws instead of waiting timeoutMs: 30_000, // per request headers: {}, // extra headers; Authorization, User-Agent and x-pump-sdk are managed warnOnDeprecation: true, // one console.warn per deprecated route; false to silence});Every request carries Authorization: Bearer <key>, Accept: application/json, User-Agent: @pump-fun/api/<version> and x-pump-sdk: @pump-fun/api/<version>. Redirects are refused so the key never follows a Location to another host, and the request() escape hatch accepts only paths under baseUrl, never an absolute URL.
Route families
Section titled “Route families”One namespace per scope. Method names follow the OpenAPI operationId.
| Namespace | Scope | Routes | Examples |
|---|---|---|---|
api.profiles |
profiles.read |
13 | getUser, searchUsers, getUsersBatch, resolveIdentifiers |
api.graph |
graph.read |
17 | getFollowers, getFollowing, checkFollows, getGroupMembers |
api.content |
content.read |
18 | getCallout, listUserCallouts, getRecentCallouts, listPosts |
api.leaderboards |
leaderboards.read |
11 | getPnlLeaderboard, listCompetitions, getCreatorPayoutsLeaderboard |
api.positions |
positions.read |
7 | getUserPositions, getUserTrades, getCoinHolderPositions |
api.moderation |
moderation.read |
1 | checkAddressBanned (outside every default grant) |
ROUTES exports the full table (method, path, operationId, scope) and listRoutes() flattens it.
// graph.read: who follows a user, paginated with limit/offsetconst { data: followers } = await api.graph.getFollowers({ userId: user.address, query: { limit: 50, offset: 0 },});
// leaderboards.read: the weekly PnL leaderboardconst { data: board } = await api.leaderboards.getPnlLeaderboard({ query: { period: 'weekly', limit: 25 } });
// positions.read: a wallet's positions in the given coinsconst { data: positions } = await api.positions.getUserPositions({ userId: user.address, query: { mints: ['<coin mint>'] },});Errors and retries
Section titled “Errors and retries”On 429, 5xx and connection failures the client retries up to maxRetries times (default 2), waiting for Retry-After when the response carries it, else the body’s retryAfterMs, else an exponential backoff from 500 ms with jitter. If a single wait would exceed maxRetryDelayMs (default 30 s) the error is thrown at once so you can schedule the retry yourself. No other 4xx is retried, and timeouts are not retried.
Once retries are exhausted, every non-2xx response throws a PumpApiError:
| Field | Meaning |
|---|---|
status |
HTTP status; 0 for timeouts and connection failures. |
code |
error from the envelope, a route code such as CALLOUT_NOT_FOUND, or one of the SDK’s own: HTTP_ERROR, TIMEOUT, NETWORK_ERROR. |
method, path |
The request that failed. |
requestId, apiKeyId |
The X-Request-Id and x-pump-api-key-id headers; quote the first in support requests. |
retryAfterMs, retryAfter |
From Retry-After (seconds or HTTP-date) or the body’s retryAfterMs; set on 429 and 503. |
rateLimit |
Parsed X-RateLimit-* headers. |
requiredScope, window, limit |
Details on API_SCOPE_FORBIDDEN and API_KEY_RATE_LIMITED. |
body, envelope, headers |
The raw body, the parsed envelope when the body was one, and the response headers. |
isRetryable, isAuthError |
Convenience flags. |
PumpApiTimeoutError (code: 'TIMEOUT') and PumpApiNetworkError (code: 'NETWORK_ERROR') extend PumpApiError. A caller signal abort propagates as an AbortError.
const address = '<wallet address>';
try { await api.moderation.checkAddressBanned({ address });} catch (err) { if (err instanceof PumpApiError && err.code === 'API_SCOPE_FORBIDDEN') { // request moderation.read through support } else { throw err; }}Deprecations
Section titled “Deprecations”A deprecated route answers with Deprecation, Sunset and Link headers. The client parses them into result.deprecation (announced and sunset as dates, successor from the Link header’s rel="successor-version", docs from a rel="deprecation" link if the API ever sends one, and the raw header values) and emits one console.warn per route per client instance. Pass warnOnDeprecation: false to the constructor to silence the warning and act on result.deprecation yourself, for example by counting it in your metrics. Routes are deprecated with at least 90 days’ notice; see Versioning and deprecation.
Key format helper
Section titled “Key format helper”import { isValidKeyFormat, parseKey } from '@pump-fun/api';
isValidKeyFormat('pf_live_...'); // prefix + 43 base62 body + 6 base62 CRC-32 checksum = 57 charsparseKey('pf_live_...'); // { ok: true, body, checksum, displayPrefix, last4 } | { ok: false, reason }The constructor itself checks only the prefix, length and character set; use isValidKeyFormat when you want the checksum verified, for example when reading the key from configuration.