Official SDKs · v0.1.3 · MIT

# PokéWallet SDKs for TypeScript and Python

Source: https://pokewallet.io/developers/sdk

Official TypeScript and Python SDKs for the PokéWallet card price API. One interface for Pokémon, One Piece and ten more trading card games, with TCGPlayer (USD) and CardMarket (EUR) prices, typed results, automatic pagination and typed errors.

[Get a free API key](https://pokewallet.io/dashboard)

[View on GitHub](https://github.com/pokewallet-lab/pokewallet-sdk)

## TypeScript

@pokewallet/sdk

```
npm install @pokewallet/sdk
```

- Node 18+
- zero dependencies
- ESM + CJS
- [npm](https://www.npmjs.com/package/@pokewallet/sdk)

## Python

pokewallet

```
pip install pokewallet
```

- Python 3.9+
- httpx only
- sync + async
- [PyPI](https://pypi.org/project/pokewallet/)

## Quickstart

1. [Create a free key](https://pokewallet.io/dashboard) in the dashboard. Keys start with `pk_`.
2. Put it in `POKEWALLET_API_KEY`. The SDKs read it by themselves.
3. Run the first script below. Free keys can search and read cards and sets.

*TypeScript*

```typescript
import { PokeWallet } from '@pokewallet/sdk'

const pw = new PokeWallet() // reads POKEWALLET_API_KEY

const results = await pw.pokemon.search('charizard', { limit: 3 })
for (const card of results.items) {
  const usd = card.tcgplayer?.prices[0]?.market  // TCGPlayer market price
  const eur = card.cardmarket?.prices[0]?.trend // CardMarket trend price
  console.log(`${card.name} | ${card.setName} #${card.number} | $${usd} / €${eur}`)
}

// Every page of a set, without handling page numbers
let count = 0
for await (const c of pw.pokemon.setCards('PLF', { maxItems: 120 })) count++

// Other games use the same methods
const lotus = await pw.games.mtg.search('black lotus', { limit: 2 })
const luffy = await pw.onepiece.search('luffy', { limit: 2 })
```

*Python*

```python
from pokewallet import PokeWallet

pw = PokeWallet()  # reads POKEWALLET_API_KEY

results = pw.pokemon.search("charizard", limit=3)
for card in results.items:
    usd = card.tcgplayer.prices[0].market if card.tcgplayer and card.tcgplayer.prices else None
    eur = card.cardmarket.prices[0].trend if card.cardmarket and card.cardmarket.prices else None
    print(f"{card.name} | {card.set_name} #{card.number} | ${usd} / €{eur}")

# Every page of a set, without handling page numbers
count = sum(1 for _ in pw.pokemon.set_cards("PLF", max_items=120))

# Other games use the same methods
lotus = pw.games.mtg.search("black lotus", limit=2)
luffy = pw.onepiece.search("luffy", limit=2)
```

*Python async*

```python
import asyncio
from pokewallet import AsyncPokeWallet

async def main():
    async with AsyncPokeWallet() as pw:
        pikachu, lotus = await asyncio.gather(
            pw.pokemon.search("pikachu", limit=2),
            pw.games.mtg.search("black lotus", limit=2),
        )
        async for card in pw.pokemon.set_cards("PLF", max_items=60):
            pass

asyncio.run(main())
```

No key yet? `health()` and `listGames()` work without one. More runnable scripts (pagination, errors, Pro endpoints, other games, async) are in the [examples folder](https://github.com/pokewallet-lab/pokewallet-sdk/tree/main/examples).

## One interface, twelve games

The API has three shapes: Pokémon, One Piece and the ten other games use different routes, set identifiers and pagination. The SDKs hide those differences, so every game answers to the same methods and returns the same fields.

`pw.pokemon`

Pokémon TCG, with price history

`pw.onepiece`

One Piece Card Game

`pw.games.<code>`

- mtg
- ygo
- lor
- fab
- dbs
- dgm
- swu
- cfv
- rft
- cpk

## Everything available

| TypeScript | Python | Returns | Access |
| --- | --- | --- | --- |
| `search(q, {page, limit})` | `search(q, page=, limit=)` | One page of cards with prices | Free |
| `searchAll(q, {limit, maxItems})` | `search_all(q, limit=, max_items=)` | Iterator over every result | Free |
| `card(id)` | `card(id)` | One card | Free |
| `sets({language})` | `sets(language=)` | All sets | Free |
| `set(code, {page, limit})` | `set(code, page=, limit=)` | One page of a set’s cards | Free |
| `setCards(code, {limit, maxItems})` | `set_cards(code, limit=, max_items=)` | Iterator over a whole set | Free |
| `imageUrl(id)` | `image_url(id)` | Image URL; fetch it with your key in the X-API-Key header | Free |
| `prices(code)` | `prices(code)` | Prices of every card in a set, one row per finish, sealed products included | Pro |
| `statistics(code, {variant})` | `statistics(code, variant=)` | Average, min, max, most expensive card, trend and rarity breakdown | Pro |
| `completionValue(code)` | `completion_value(code)` | Cost of one copy of every card in its base finish | Pro |
| `trending({limit})` | `trending(limit=)` | Sets with the biggest CardMarket price moves over 7 days | Pro |
| `topCards({metric, source, limit})` | `top_cards(metric=, source=, limit=)` | Ranking by price or by 7-day growth | Pro |
| `pokemon.priceHistory(id)` | `pokemon.price_history(id)` | Price at 7, 14, 30, 60 and 120 days | Pro · Pokémon |
| `health()` | `health()` | Service status and a check per service | No key |
| `listGames()` | `list_games()` | The ten games and their routes | No key |

**Pro** means the Pro plan for Pokémon and One Piece, or the Ultra plan for the ten other games. Every account can start a 7-day free trial from the dashboard. Without access the SDK raises `PlanRequiredError` with the link to start the trial. [See plans](https://pokewallet.io/pricing)

## Errors, retries and limits

Every failure is a typed error, all subclasses of `PokeWalletError`.

| Error | When | Useful fields |
| --- | --- | --- |
| `ValidationError` | Bad arguments, or no API key; raised before any request | — |
| `AuthError` | 401: key missing, malformed or unknown | — |
| `PlanRequiredError` | 403: the plan or trial does not cover this endpoint | `redeemUrl, upgradeUrl` |
| `FeatureNotEnabledError` | 403: the account does not have access to this feature | `contactUrl` |
| `NotFoundError` | 404: unknown card or set | `didYouMean, suggestions` |
| `GameUnavailableError` | 404 on a game route that is switched off | — |
| `AmbiguousSetError` | A set code matches several sets | `matches` |
| `RateLimitError` | 429: quota used up | `limits, retryAfter` |
| `UnavailableError` | 503: service busy | `retryAfter` |
| `NetworkError, ServerError` | No answer, or another 5xx | — |

### Retries

Only a 429 with a `Retry-After` within 30 seconds, and a 503 up to 2 times. Nothing else is retried, and the SDK never guesses a wait.

### Quota

After any call, `pw.lastRateLimit` (Python: `pw.last_rate_limit`) holds the hourly and daily limits and what is left. Error responses count against your quota too.

## Key safety

- **Read it from the environment.** Never in code, git, issues or screenshots. Call the SDK from your server, so the key never reaches a browser.
- **Masked everywhere.** The key shows as `pk_***` in logs, errors and serialization, and is removed from any server text that echoes it.
- **Leaked a key?** Revoke it in the [dashboard](https://pokewallet.io/dashboard) and create a new one. It takes a few seconds.

## Frequently asked questions

### Is there an official SDK for the Pokémon TCG API?

Yes. @pokewallet/sdk for TypeScript and pokewallet for Python are the official PokéWallet SDKs. They cover Pokémon, One Piece and ten more trading card games with one API key.

### Do I need a paid plan to use the SDKs?

No. A free key can search cards and read cards and sets (100 requests per hour, 1,000 per day). Set prices, statistics, trending sets, top cards and price history need Pro, Ultra or the 7-day free trial.

### Can I use the TypeScript SDK in the browser?

Use it on your server. The SDK needs your API key, and a key sent to a browser can be copied by anyone who opens the page.

### My language is not TypeScript or Python. What can I use?

Call the REST API directly, or generate a client from the OpenAPI 3.1 specification at https://pokewallet.io/openapi.json.

### Are the SDKs open source?

Yes, under the MIT license, on GitHub at pokewallet-lab/pokewallet-sdk. The data they return is covered by the PokéWallet Terms of Use.

## Prefer to ask your AI assistant?

The PokéWallet MCP server gives Claude Code, Cursor and other clients the same data, with the same key.

[Set up the MCP server](https://pokewallet.io/developers/mcp)
