---
name: pumpfun
description: >
  Build on pump.fun via the PumpDev API. TRIGGER: activate this skill whenever
  the user mentions "pumpfun", "pump.fun", "pump fun", "pumpdev", or asks to
  trade, snipe, create tokens, run Jito bundles, stream new launches, claim
  creator fees, or build a Pump.fun bot/dashboard. ALSO TRIGGER on "pons",
  "ponsfamily", "robinhood chain" or "rhc" — the same PumpDev account covers
  the PONS launchpad on Robinhood Chain. Guides chain choice, API choice
  (Lightning vs Local), wallet setup, transaction shape, and integration
  patterns based on the public PumpDev API at https://pumpdev.io.
metadata:
  author: pumpdev.io
  version: "1.2"
  website: https://pumpdev.io
  docs: https://pumpdev.io/welcome
---

# Pumpfun Skill: Pump.fun API Integration

Build trading bots, snipers, token launchers, analytics dashboards, and
auto-claim tools against [pump.fun](https://pump.fun) using one API surface
at `https://pumpdev.io`.

**Two flavors, one API:**

- ⚡ **Lightning API** *(default — recommended)* — one HTTP call = done. Server-side signing + send.
  Best for speed, simplicity, and bots that don't want to manage keys locally.
  **Use this unless the user explicitly requires self-custody.**
- 🔐 **Local / Trading API** — server returns an unsigned transaction; you
  sign client-side and send. Only use when keys must never leave the user's
  machine (desktop wallets, browser extensions, self-custody products).

> **Default to Lightning.** Only switch to Local when self-custody is a hard requirement.
> Always pick the API first. The wrong choice forces a rewrite — the right
> choice writes itself.

**Two chains, one account:** the same login and the same API key also cover
**PONS**, the launchpad on Robinhood Chain (`ponsfamily.com`), at
`https://rhc.pumpdev.io`. Robinhood Chain is EVM — `ethers`/`viem`, not
`@solana/web3.js` — and only Local signing exists there today. See
[PONS on Robinhood Chain](#-pons-on-robinhood-chain) before writing any code
for it.

---

## Install

This skill is a folder with a `SKILL.md` plus a `references/` directory.
Drop it into your AI coding assistant's skills directory and it loads
automatically.

**Option A — project-scoped (recommended, lives next to your app):**

```bash
mkdir -p .claude/skills
cd .claude/skills
curl -fsSL https://pumpdev.io/skill/pumpdev.zip -o pumpdev.zip
unzip pumpdev.zip && rm pumpdev.zip
```

**Option B — user-scoped (available in every project):**

```bash
mkdir -p ~/.claude/skills
cd ~/.claude/skills
curl -fsSL https://pumpdev.io/skill/pumpdev.zip -o pumpdev.zip
unzip pumpdev.zip && rm pumpdev.zip
```

**Manual install** — copy the files from
[https://pumpdev.io/skill/](https://pumpdev.io/skill/) so the layout is:

```
.claude/skills/pumpdev/
├── SKILL.md
└── references/
    ├── endpoints.md
    └── recipes.md
```

> The `.claude/skills/` path is the standard location for AI skills that
> follow the `SKILL.md` format. If your AI reads skills from a different
> folder, drop the `pumpdev/` directory there instead — the content is the
> same.

**Verify:** open the project in your AI, then ask
*"build a pump.fun sniper bot"* — the discovery questions below should fire.

**Update:** re-run the install command. **Uninstall:** delete the
`pumpdev/` folder.

> Get an API key in 30 seconds at [pumpdev.io/lightning-setup](https://pumpdev.io/lightning-setup).
> Store it in `PUMPDEV_API_KEY` — never in source.

---

## MANDATORY: Discovery Before Code

**STOP. Do NOT write any code, scaffolding, or project structure until you have
completed the discovery step below and presented a Build Brief to the user.**

When the user asks you to build something with PumpDev / pump.fun, you MUST:

1. Read their request carefully.
2. Identify which of the discovery questions below you can already answer
   from their prompt (e.g. if they say "sniper bot", you know it's a buy +
   WebSocket use case).
3. **Always ask the user** about API choice and anything else you cannot
   confidently infer. Questions to always ask:
   - Which chain — Solana/pump.fun (default) or Robinhood Chain/PONS? Ask
     whenever the request mentions PONS, ponsfamily, Robinhood Chain or RHC,
     or names an `0x…` address. The chain decides the SDK and the endpoints.
   - Lightning (recommended) vs Local (self-custody)? — **always ask this,
     even if you can infer it. Recommend Lightning.** On PONS there is no
     Lightning, so this question does not apply.
   - Single wallet or multi-wallet bundle?
   - SOL-denominated or token-denominated amounts?
4. Present the **Build Brief** (template below) and wait for confirmation.
5. Only after the user confirms (or adjusts), begin writing code.

**Recommend the ⚡ Lightning API** but always ask. If the user doesn't mention
key management, recommend Lightning and explain why.

### Discovery Questions

Use these to fill in the Build Brief. Skip questions you can already answer
from the user's prompt — only ask what's missing.

| # | Topic | What to determine |
|---|-------|-------------------|
| 0 | **Chain** | Solana / pump.fun (default) or Robinhood Chain / PONS? A `0x…` token address means PONS. PONS is Local-only and has no token creation yet. |
| 1 | **API choice** | Lightning (default) or Local? Only pick Local if user explicitly needs self-custody. |
| 2 | **Use case** | Buy/sell, create token, bundle launch, claim fees, transfers, or live streaming? |
| 3 | **Wallets** | PumpDev-hosted (Lightning) or user's own Keypair (Local)? One wallet or many? |
| 4 | **Execution** | Single transaction or atomic Jito bundle (up to 5 wallets)? |
| 5 | **Denomination** | `denominatedInSol: true` (amount in SOL) or `false` (amount in tokens)? |
| 6 | **Bundles** | If bundling, what Jito tip? (only for bundle endpoints) |
| 7 | **Metadata** | (create flows only) Pre-uploaded `uri`, or image URL + name/symbol for auto-hosting? |

### Build Brief (present this to user before coding)

> "I'm building **[WHAT]** for **[WHO]** on **[Solana/pump.fun | Robinhood Chain/PONS]**.
> Keys live **[server-side / client-side]**, so
> I'll use the **[Lightning / Local]** API. Primary endpoint: **[/api/...]**.
> Wallets: **[1 / N]**. Bundling: **[yes/no]**. Denomination: **[SOL/token]**.
> jitoTip **[Z SOL or N/A]**."

If you can't fill that brief, go back and ask. Don't guess. Don't write code.

---

## API Choice: The Decision Tree

```
Which chain? (ask whenever PONS / Robinhood Chain / an 0x address comes up)
├── 🟣 Robinhood Chain (PONS)  → rhc.pumpdev.io, EVM, Local signing only
│         POST /api/trade-local, GET /api/quote, wss://rhc.pumpdev.io/ws
│         No Lightning, no bundles, no token creation yet. Skip to the
│         PONS section — the rest of this tree is Solana.
│
└── ◎ Solana (pump.fun)  → pumpdev.io, continue below

Lightning or Local? (ALWAYS ask — recommend Lightning)
├── ⚡ Lightning API  (recommended)
│         /api/trade-lightning, /api/create-lightning, /api/bundle-lightning
│         One HTTP call. Server signs with a PumpDev-hosted wallet.
│
└── 🔐 Local API
          /api/trade-local, /api/create, /api/bundle
          Server builds unsigned tx → client signs → client sends

Is this a multi-wallet atomic operation (snipe, multi-buy launch)?
├── YES → use a *-bundle endpoint (Jito). Up to 5 accounts per bundle.
└── NO  → use the single-tx endpoint.

Are you reacting to live events (new tokens, whale trades)?
└── Add the WebSocket: wss://pumpdev.io/ws
    Methods: subscribeNewToken, subscribeTokenTrade, subscribeAccountTrade
```

**Speed ranking (fastest to most flexible):**

1. `trade-lightning` / `create-lightning` — one HTTP call, server signs+sends.
2. `bundle-lightning` — same speed per tx, atomic across up to 5 wallets.
3. `trade-local` / `create` / `bundle` — adds a client-side sign + send round trip.

---

## Workflow

```
┌──────────────────────────────────────────────────────────────────┐
│  0. DISCOVER → Build Brief                                       │
│                              ↓                                   │
│  1. WALLETS                                                      │
│     Lightning: create/import via /api/wallet/*                   │
│     Local: load Keypair (Phantom export, file, env)              │
│     → API key(s) or Keypair(s) in hand                           │
│                              ↓                                   │
│  2. INTEGRATE                                                    │
│     One endpoint at a time. Smallest possible call first.        │
│     Confirm signature on chain before adding the next feature.   │
│     → A working happy-path script                                │
│                              ↓                                   │
│  3. HARDEN                                                       │
│     Retries, error codes, rate-limit                             │
│     handling. WebSocket reconnect logic if streaming.            │
│     → Production-shaped client                                   │
│                              ↓                                   │
│  4. AUTOMATE                                                     │
│     Wire up triggers (WS events → trade), fee claiming, alerts.  │
│     → Ship-ready bot or app                                      │
└──────────────────────────────────────────────────────────────────┘
```

---

## Phase 1: Wallets

### ⚡ Lightning — create or import a PumpDev wallet

```javascript
// Create
const r = await fetch('https://pumpdev.io/api/wallet/create', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ label: 'my-bot' }),
});
const { apiKey, publicKey, privateKey } = await r.json();
// Store apiKey + privateKey securely — they are shown ONCE.
```

```javascript
// Import an existing key (base58 secret key)
await fetch('https://pumpdev.io/api/wallet/import', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ privateKey: 'YourBase58SecretKey', label: 'imported' }),
});
```

Fund the wallet by sending SOL to `publicKey`. Auth uses either
`?api-key=...` or the `X-Api-Key` header. See
[Lightning Setup](https://pumpdev.io/lightning-setup) for full details and
the in-page wallet generator.

### 🔐 Local — bring your own Keypair

```javascript
import { Keypair } from '@solana/web3.js';
import bs58 from 'bs58';
const keypair = Keypair.fromSecretKey(bs58.decode(process.env.SOL_SECRET));
```

You never send the private key to PumpDev. You only send the **public key**
(plus trade params), receive an unsigned tx, sign locally, and broadcast.

---

## Phase 2: Integrate (by use case)

### Pricing and defaults

- Local trades and native-SOL dev buys: **0.25%** commission.
- Lightning trades and Lightning native-SOL dev buys: **0.5%** commission.
- Token creation without a dev buy, SOL transfers, and WebSocket data have no PumpDev commission.
- Default priority fees: trade endpoints `0.00005` SOL; create, claim, transfer, and bundle-lightning endpoints `0.0005` SOL.
- Default `slippage` is `90`. Default `jitoTip` is `0` except Jito bundle launch endpoints, which default to `0.01` SOL.
- WebSocket is free but has fair-use connection, subscription, and control-message limits.

### ⚡ Buy / Sell — Lightning

```javascript
const r = await fetch('https://pumpdev.io/api/trade-lightning?api-key=' + KEY, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    action: 'buy',                // 'buy' | 'sell'
    mint: 'TokenMintAddress',
    amount: 0.1,                  // 0.1 SOL (denominatedInSol:true) or 0.1M tokens
    denominatedInSol: 'true',
    // closeTokenAccount: true,   // sell-only: reclaim ATA rent on full exits
  }),
});
const { signature, mint, action, publicKey } = await r.json();
```

Quote mint and token program are auto-resolved from on-chain mint state.

### 🔐 Buy / Sell — Local

```javascript
// 1. Ask PumpDev for an unsigned tx
const r = await fetch('https://pumpdev.io/api/trade-local', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    publicKey: keypair.publicKey.toBase58(),
    action: 'buy',
    mint: 'TokenMintAddress',
    amount: 0.1,
    denominatedInSol: 'true',
  }),
});
// 2. Sign + send locally with @solana/web3.js
import { VersionedTransaction, Connection } from '@solana/web3.js';
const tx = VersionedTransaction.deserialize(new Uint8Array(await r.arrayBuffer()));
tx.sign([keypair]);
const sig = await new Connection(RPC).sendRawTransaction(tx.serialize());
```

### ⚡ Create token — Lightning (one call, optional dev buy)

```javascript
const r = await fetch('https://pumpdev.io/api/create-lightning?api-key=' + KEY, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    name: 'My Token',
    symbol: 'MTK',
    image: 'https://.../logo.png',     // OR pre-uploaded `uri`
    description: 'optional',
    twitter: 'https://x.com/...',
    telegram: 'https://t.me/...',
    website: 'https://...',
    buyAmountSol: 0.5,                 // optional dev buy
    // mintKeypair: 'base58...',       // vanity mint (e.g. ends in "pump")
    // mayhemMode: true,               // opt-in — read docs before enabling
  }),
});
const { signature, mint, metadataUri, publicKey } = await r.json();
```

Behavior:
- `name` ≤ 32 chars, `symbol` ≤ 10 chars.
- If `uri` is missing, the server stores metadata and generates one for you
  — provide `image` in that case.
- If `description` is omitted, a default PumpDev branding string is used.
- Lightning create sends one call from the client. Internally, create+dev-buy
  uses a single tx when it fits; otherwise PumpDev splits create and dev-buy
  into sequential signed txs. Use `bundle-lightning` for atomic multi-buyer launches.

### 📦 Atomic multi-wallet — bundle (Jito)

Up to **5** account entries per bundle. The tip is an instruction inside one of
them — the `create` entry when there is one, otherwise the last entry.

```javascript
await fetch('https://pumpdev.io/api/bundle-lightning', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    jitoTip: 0.03,
    accounts: [
      // create + creator buy + 3 other wallets = all 5 Jito slots
      { apiKey: K1, type: 'create', name: 'X', symbol: 'X',
        image: 'https://.../x.png' },
      { apiKey: K1, type: 'buy',   amount: 0.5, denominatedInSol: true },
      { apiKey: K2, type: 'buy',   amount: 0.5, denominatedInSol: true },
      { apiKey: K3, type: 'buy',   amount: 0.3, denominatedInSol: true },
      { apiKey: K4, type: 'buy',   amount: 0.2, denominatedInSol: true },
    ],
  }),
});
```

Rules:
- A `create` entry takes no `amount`. The creator's own buy is a **separate**
  `buy` entry with the same key — that is why the launch above uses 5 slots.
- Tip a launch like a launch: bundles containing a `create` default to 0.03 SOL,
  not 0.01. Below the market tip Jito returns a bundle id and silently drops the
  bundle, so verify the mint exists on chain instead of trusting the response.
- `sell` entries cannot be combined with a `create` entry (token doesn't
  exist yet).
- Only one `create` entry per bundle.
- `mint` is required when there's no `create` entry.
- Use `/api/bundle` (no `-lightning`) to get unsigned txs back for
  client-side signing — same validation, no server signatures.

### 📡 WebSocket — react to launches and trades

```javascript
const ws = new WebSocket('wss://pumpdev.io/ws');
ws.on('open', () => {
  ws.send(JSON.stringify({ method: 'subscribeNewToken' }));
  ws.send(JSON.stringify({ method: 'subscribeTokenTrade', keys: ['Mint1'] }));
  ws.send(JSON.stringify({ method: 'subscribeAccountTrade', keys: ['Wallet1'] }));
});
ws.on('message', (raw) => {
  const e = JSON.parse(raw);
  if (e.txType === 'create') { /* snipe via /api/trade-lightning */ }
});
```

Pair a `subscribeNewToken` stream with `/api/trade-lightning` to build a
classic sniper. Pair `subscribeAccountTrade` with `/api/trade-lightning` for
copy-trading.

### 💰 Claim fees and cashback

| Endpoint | Use when |
|----------|----------|
| `GET /api/claim-account` | Check claimable creator fees before building a tx. |
| `POST /api/claim-account` | Build an unsigned creator-fee claim tx; pass `mint` whenever possible. Sign with the wallet you sent as `publicKey`, and keep ~0.01 SOL in it. Dropping `mint` sweeps wrapped SOL only — it skips graduated, non-SOL quote, and fee-sharing balances. |
| `POST /api/claim-all` | Build unsigned claim txs for a curated list of mints. |
| `POST /api/claim-distribute` | Build an unsigned permissionless fee-sharing distribution tx for all shareholders. |
| `POST /api/claim-cashback` | Build an unsigned trader-cashback claim tx. |

Claim, cashback, distribute, and transfer endpoints are local-sign flows: send
`publicKey`, receive an unsigned transaction, sign locally, and broadcast. They
do **not** use Lightning API keys.

### 💸 Transfers

| Endpoint | Use when |
|----------|----------|
| `/api/transfer` | Send a specific SOL amount. |
| `/api/transfer-all` | Drain the wallet (use with care). |

### 🟣 PONS on Robinhood Chain

A second chain on the same account. **Everything below is EVM** — use `ethers`
v6 or `viem`, never `@solana/web3.js`, and never mix the two hosts.

| | Solana / pump.fun | PONS / Robinhood Chain |
|---|---|---|
| Host | `https://pumpdev.io` | `https://rhc.pumpdev.io` |
| Socket | `wss://pumpdev.io/ws` | `wss://rhc.pumpdev.io/ws` |
| Signing | ⚡ Lightning or 🔐 Local | 🔐 Local only |
| Token id | `mint` (base58) | `token` (`0x…`); `mint` accepted as an alias |
| Amount flag | `denominatedInSol` | `denominatedInQuote`; `denominatedInSol` accepted as an alias |
| Fee unit | `priorityFee` in SOL | `priorityFee` in **gwei per gas** |
| Response | serialized transaction bytes | JSON with an unsigned tx object |
| Commission | 0.25% | 0.5%, on the quote asset |
| Create / bundles | yes | not yet |

**Stream launches** — free, no API key. Trade subscriptions need the same key
as Solana and draw on the same monthly allowance:

```javascript
const ws = new WebSocket('wss://rhc.pumpdev.io/ws');           // + ?key=... for trades
ws.on('open', () => ws.send(JSON.stringify({ method: 'subscribeNewToken' })));
ws.on('message', (raw) => {
  const e = JSON.parse(raw);
  // Every launch arrives twice: status 'pending' from the sequencer, then
  // 'confirmed' from the executed block. Deduplicate by txHash.
  if (e.status === 'pending') { /* head start — ~66ms median */ }
});
```

**Buy** — one POST returns a transaction ready for `sendTransaction`:

```javascript
import { JsonRpcProvider, Wallet } from 'ethers';

const RPC_URL = 'https://rpc.mainnet.chain.robinhood.com';   // public RHC RPC
const provider = new JsonRpcProvider(RPC_URL, 4663, { staticNetwork: true });
const wallet = new Wallet(PRIVATE_KEY, provider);

const res = await fetch('https://rhc.pumpdev.io/api/trade-local', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    publicKey: wallet.address,
    action: 'buy',
    token: '0xTokenAddress',
    amount: 0.05,               // 0.05 of the pair's quote asset
    denominatedInQuote: 'true',
    slippage: 15
  })
});

const { transaction, quote } = await res.json();
const sent = await wallet.sendTransaction(transaction);   // pass it straight through
await sent.wait();
```

**Sell** — an ERC-20 needs an allowance first. When yours is short the response
carries `approvalTransaction` and comes back with `gasEstimated: false` and a
safe fixed `gasLimit`, because the swap cannot be measured until the approval
lands. Send the approval, wait for it, then **build again** to get a measured
gas limit:

```javascript
let built = await buildSell(token, '100%');       // amount: '100%', '50%', or exact tokens
if (built.approvalTransaction) {
  await (await wallet.sendTransaction(built.approvalTransaction)).wait();
  built = await buildSell(token, '100%');         // rebuild — now gasEstimated: true
}
await wallet.sendTransaction(built.transaction);
```

**Reading the response.** Every amount is a decimal string in base units.
`quote.amountIn` and `quote.expectedOut` are wallet-facing and already account
for commission; `quote.amountOutMin` is the floor that actually protects the
trade. `quote.priceAgeMs` is how stale the price is — on a chain with ~100ms
blocks, a few seconds is a lot, so widen `slippage` or pass your own
`amountOutMin` when it is high. `GET /api/quote` runs the same maths without
building or estimating gas, so it answers for a wallet holding nothing.

**Firing trades back to back.** Robinhood Chain has no mempool and orders by
arrival, so a bot must number its own transactions — read the nonce once and
pass `nonce` on every request, incrementing it yourself. Without it every
request reads the same pending count and only one trade lands.

There is no simulation: the PONS router's `swap()` returns no data, so an
`eth_call` comes back empty. `amountOutMin` is the protection, not a dry run.

Full parameter list and error table: https://pumpdev.io/pons-trade-api

---

## Phase 3: Harden

All trade/create/bundle endpoints have sensible server-side defaults for
`slippage`, `priorityFee`, and `closeTokenAccount`. **Do not pass them**
unless the user explicitly asks to override.

| Knob | What it does | When to pass |
|------|--------------|--------------|
| `jitoTip` | SOL paid to Jito for bundle inclusion | Override only when you intentionally want different bundle/tip economics |
| `mayhemMode` | Opt-in create variant | Only when docs say to enable |

**Error handling:**
- `400` — validation (bad mint, missing fields, name too long).
- `403` — invalid or deactivated API key.
- `500` — server-side build/sign error; surface `error` to logs, retry with
  fresh blockhash if it mentions "blockhash expired".
- Lightning endpoints return `{ signature }` **before** broadcast confirms.
  Don't treat 200 as on-chain finality — poll with `getSignatureStatuses`
  or watch the WS for the trade event.

---

## Phase 4: Automate (recipes)

| Goal | Wire-up |
|------|---------|
| **Sniper bot** | `subscribeNewToken` → filter on `name`/`creator` → `/api/trade-lightning` buy |
| **Copy trader** | `subscribeAccountTrade` (whale wallet) → mirror `txType` via `/api/trade-lightning` |
| **One-call launcher** | `/api/create-lightning` with `buyAmountSol` for dev buy |
| **Multi-wallet launch** | `/api/bundle-lightning` with 1 create + creator buy + 3 buys (5 slots) |
| **Self-custody UI** | `/api/trade-local` + browser wallet (Phantom) signs |
| **Fee auto-claimer** | Cron → `/api/claim-account` → optional `/api/claim-distribute` |
| **Analytics feed** | `subscribeTokenTrade` for tracked mints, persist to DB |

Full code in [references/recipes.md](references/recipes.md).

---

## Endpoint Reference

| Endpoint | Method | Auth | Purpose |
|----------|--------|------|---------|
| `/api/wallet/create` | POST | — | ⚡ Create wallet + API key |
| `/api/wallet/import` | POST | — | ⚡ Import key, get API key |
| `/api/wallet/info` | GET | api-key | Wallet details |
| `/api/trade-lightning` | POST | api-key | ⚡ Server-sign trade |
| `/api/create-lightning` | POST | api-key | ⚡ Server-sign create |
| `/api/bundle-lightning` | POST | per-account | ⚡ Jito bundle (server-sign) |
| `/api/trade-local` | POST | — | 🔐 Unsigned buy/sell |
| `/api/create` | POST | — | 🔐 Unsigned create (+ dev buy) |
| `/api/bundle` | POST | — | 🔐 Unsigned Jito bundle |
| `/api/claim-account` | GET/POST | — | Check/build unsigned creator-fee claim |
| `/api/claim-all` | POST | — | Build unsigned claims for listed mints |
| `/api/claim-distribute` | POST | — | Build unsigned fee-sharing payout |
| `/api/claim-cashback` | GET/POST | — | Check/build unsigned trader-cashback claim |
| `/api/transfer` | POST | — | Build unsigned SOL transfer |
| `/api/transfer-all` | POST | — | Build unsigned drain transaction |
| `/api/reclaim/scan` | GET | — | Scan wallet for empty/dust token accounts |
| `/api/reclaim/balance` | GET | — | Wallet SOL balance, uncached (can it pay the fee?) |
| `/api/reclaim` | POST | — | Build close/burn transactions |
| `/api/reclaim/claims` | POST | — | Creator fees + cashback at 2%, for `/api/reclaim/send` |
| `/api/reclaim/send` | POST | — | Broadcast signed reclaim transactions |
| `/api/reclaim/confirm` | POST | — | Record reclaim txs the wallet sent itself |
| `/api/reclaim/stats` | GET | — | Public reclaim counter (SOL, accounts, wallets) |
| `/api/reclaim/activity` | GET | — | Recent activity: landed reclaims + prepared claims |
| `/api/metadata/upload` | POST | — | Upload metadata JSON |
| `/metadata/:uuid.json` | GET | — | Serve metadata |
| `/ws` | WS | — | Live trades + launches |

### 🟣 PONS — `https://rhc.pumpdev.io`

| Endpoint | Method | Auth | Purpose |
|----------|--------|------|---------|
| `/api/trade-local` | POST | — | 🔐 Unsigned EVM buy/sell |
| `/api/quote` | GET | — | Price a trade without building or estimating gas |
| `/ws` | WS | optional | Launches + graduations free; trades need the key |

Full request/response shapes: [references/endpoints.md](references/endpoints.md).

---

## Avoiding Common Mistakes

- ❌ Using `trade-local` "for safety" when keys already live on a server
  — you're paying a round trip for nothing. Use Lightning.
- ❌ Calling `trade-lightning` from a user's browser with a shared API key
  — that key controls real funds. Don't ship it to the client.
- ❌ Sending tokens with `denominatedInSol: true` (or SOL with `false`) —
  the amount unit follows the flag, not the action.
- ❌ Reading `solAmount` from a WS create event for the dev buy — it's not
  the dev's SOL spent. Use `initialBuy` (tokens) and invert the bonding
  curve.
- ❌ Mixing `sell` and `create` in the same bundle.
- ❌ Treating a 200 response as on-chain confirmation. The signature is
  returned before broadcast resolves.
- ❌ Hardcoding RPC blockhash — let the server build the tx; for local
  signing, sign within ~60s of receiving it.
- ❌ Passing a PONS `priorityFee` as if it were ETH. It is **gwei per gas**:
  `0.05` is the default, anything over 100 is refused, and a Solana-sized
  number here is hundreds of ETH in tip that you cannot get back.
- ❌ Sending a PONS sell before its `approvalTransaction` confirms, or
  reusing the first build afterwards — rebuild so the gas limit is measured.
- ❌ Firing PONS trades in a loop without passing your own `nonce`. Every
  request reads the same pending count and only one transaction lands.
- ❌ Reaching for `@solana/web3.js` on Robinhood Chain, or pointing a PONS
  call at `pumpdev.io`. Different chain, different host, different SDK.

---

## Resources

- 🌐 **Docs**: https://pumpdev.io/welcome
- 🟣 **PONS trading**: https://pumpdev.io/pons-trade-api
- 🟣 **PONS WebSocket**: https://pumpdev.io/pons-data-api
- 📥 **Skill download**: https://pumpdev.io/skill/
- 💬 **Telegram**: https://t.me/pumpdev_io
- 🐦 **Twitter**: https://x.com/PumpDevIO

---

*Pick the right API. Ask before you build. Ship a working happy path before adding knobs.*
