One Piece
API Documentation
Complete REST reference for the One Piece Card Game API. Real-time prices from TCGPlayer and CardMarket, full card and set database for all OPCG sets.
https://api.pokewallet.io/cards, /sets…, One Piece at /op/…, the other games at /mtg/…, /ygo/…, /lor/… and so on. Quick Start
Start fetching One Piece card data in seconds:
Make Your First Request
Fetch all One Piece sets with a single call:
curl https://api.pokewallet.io/op/sets \
-H "X-API-Key: YOUR_API_KEY"Fetch a Specific Set
Get all cards in OP01 — Romance Dawn:
curl https://api.pokewallet.io/op/sets/OP01 \
-H "X-API-Key: YOUR_API_KEY"Authentication
All API requests (except /health) require authentication using an API key.
API Key Format
API keys follow this format:
- Production keys:
pk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - Development keys:
pk_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Authentication Methods
You can authenticate using either the X-API-Key header or Authorization header:
curl -H "X-API-Key: pk_live_your_key_here" \
"https://api.pokewallet.io/search?q=pikachu"curl -H "Authorization: Bearer pk_live_your_key_here" \
"https://api.pokewallet.io/search?q=pikachu"Rate Limits
Rate limits vary depending on your subscription plan:
Rate limits are shared across Pokémon and One Piece endpoints.
| Plan | Hourly Limit | Daily Limit | Price |
|---|---|---|---|
| Free | 100 requests | 1,000 requests | $0/month |
| Early Access ⭐ | 1,000 requests | 10,000 requests | No longer available |
| Coffee ☕ | 1,000+ requests | 10,000+ requests | Buy a coffee on Ko-fi |
| Pro | 5,000 requests | 50,000 requests | €20/month |
| Ultra | 7,000 requests | 70,000 requests | €29/month |
| Business | Custom | Custom | Contact us |
Early Access was our initial launch tier and is no longer available for new users.
Rate Limit Headers
Every API response includes rate limit information:
X-RateLimit-Limit-Hour: 100
X-RateLimit-Remaining-Hour: 95
X-RateLimit-Limit-Day: 1000
X-RateLimit-Remaining-Day: 823Rate Limit Exceeded (429)
When you exceed your rate limit, you'll receive a 429 Too Many Requests response:
{
"error": "Rate limit exceeded",
"message": "Hourly limit exceeded",
"limits": {
"hourly": {
"limit": 100,
"used": 100,
"remaining": 0
},
"daily": {
"limit": 1000,
"used": 523,
"remaining": 477
}
}
}Public Endpoints
/healthNo Auth RequiredCheck API status, database, cache, and storage health with response times.
Example Request:
curl "https://api.pokewallet.io/health"Response Example (Healthy):
{
"status": "healthy",
"timestamp": "2025-12-16T10:30:00.000Z",
"version": "1.1.0",
"checks": {
"database": {
"status": "healthy",
"responseTime": 45
},
"cache": {
"status": "healthy",
"responseTime": 3
},
"storage": {
"status": "healthy",
"responseTime": 12
}
},
"responseTime": 60,
"region": "FRA"
}Response Example (Unhealthy):
{
"status": "unhealthy",
"timestamp": "2025-12-16T10:30:00.000Z",
"version": "1.1.0",
"message": "Critical services unavailable - API may not function correctly",
"checks": {
"database": {
"status": "unhealthy",
"responseTime": null,
"message": "Connection failed"
},
"cache": {
"status": "healthy",
"responseTime": 3
},
"storage": {
"status": "healthy",
"responseTime": 12
}
},
"responseTime": 1050,
"region": "FRA"
}/No Auth RequiredGet API information, version, and available endpoints.
Example Request:
curl "https://api.pokewallet.io/"Response Example:
{
"name": "PokeWallet API",
"version": "1.1.0",
"status": "production",
"authentication": {
"required": true,
"method": "API Key",
"header": "X-API-Key",
"format": "pk_live_xxxxxxxxxxxxx"
},
"endpoints": {
"health": { "path": "/health", "auth_required": false },
"search": { "path": "/search?q=charizard&limit=20", "auth_required": true },
"cardDetail": { "path": "/cards/:id", "auth_required": true },
"sets": { "path": "/sets", "auth_required": true },
"setDetails": { "path": "/sets/:setCode?page=1&limit=50", "auth_required": true },
"images": { "path": "/images/:id?size=high", "auth_required": true }
},
"rate_limits": {
"per_hour": 100,
"per_day": 1000,
"plan": "free"
}
}/gamesNo Auth RequiredLists the games available under their own prefix (/mtg, /ygo, …) with their routes. Pokémon and One Piece are not in this list: they use /cards, /sets… and /op/….
Example Request:
curl "https://api.pokewallet.io/games"Response Example (first of ten games):
{
"success": true,
"data": [
{
"code": "mtg",
"name": "Magic: the Gathering",
"endpoints": {
"sets": "/mtg/sets",
"set": "/mtg/sets/:set",
"card": "/mtg/cards/:id",
"search": "/mtg/search?q=",
"image": "/mtg/images/:id"
}
}
]
}Pro (€20/month) covers Pokémon and One Piece only. Ultra (€29/month) includes everything in Pro plus the paid endpoints of the other 10 games: Magic, Yu-Gi-Oh!, Lorcana and more.
Compare plans →Sets Endpoints
/op/setsReturns all One Piece sets ordered by release date.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
language | string | Optional | Filter by language: en or jp |
Example Request:
curl -H "X-API-Key: pk_live_your_key_here" \
"https://api.pokewallet.io/op/sets?language=en"Response Example:
{
"success": true,
"data": [
{
"name": "Romance Dawn",
"set_code": "OP01",
"group_id": "3188",
"language": "en",
"release_date": "2022-12-02"
},
{
"name": "Paramount War",
"set_code": "OP02",
"group_id": "3189",
"language": "en",
"release_date": "2023-03-10"
}
],
"total": 100
}group_id is the numeric identifier for the set in the DB. Positive = TCG set, negative = CM-only set (no TCGPlayer data). Set images are not available for One Piece sets. /op/sets/:setCodeReturns a paginated card list for a specific One Piece set.
Path Parameter:
| Value | Behavior |
|---|---|
OP01 | Lookup by set_code (case-insensitive) |
3188 | Lookup by numeric group_id |
-8 | CM-only set (negative group_id) |
EB01 | Fuzzy fallback: automatically tries EB-01 |
Query Parameters:
| Parameter | Default | Max |
|---|---|---|
page | 1 | — |
limit | 50 | 200 |
Example Request:
curl -H "X-API-Key: pk_live_your_key_here" \
"https://api.pokewallet.io/op/sets/OP01?page=1&limit=50"Response Example:
{
"success": true,
"set": {
"set_code": "OP01",
"group_id": "3188",
"name": "Romance Dawn",
"language": "en",
"release_date": "2022-12-02"
},
"total": 50,
"page": 1,
"limit": 50,
"data": [
{
"id": "op_3f8a12c4e9b7d02f...",
"card_number": "OP01-001",
"name": "Roronoa Zoro",
"clean_name": "Roronoa Zoro",
"sub_type_name": "Normal",
"rarity": "L",
"card_type": "Leader",
"ext_color": "Red",
"ext_cost": null,
"ext_power": "5000",
"ext_life": "5",
"ext_subtypes": "Straw Hat Crew;Supernovas",
"ext_attribute": "Slash",
"ext_counterplus": null,
"ext_description": "[DON!! x1] ...",
"tcgplayer": {
"url": "https://www.tcgplayer.com/product/...",
"prices": {
"low_price": 1.20,
"market_price": 1.76,
"high_price": 3.50
}
},
"cardmarket": {
"product_name": "Roronoa Zoro (OP01-001)",
"product_url": "https://www.cardmarket.com/...",
"prices": { "avg": 1.64, "low": 0.50, "trend": 1.70 }
}
}
]
}group_id): cards have tcgplayer: null and no ext_* fields. total is the full card count for the set (not just the current page). Each card also includes a clean_name field (normalized name without special characters). Cards Endpoints
/op/cards/:idReturns details for a single One Piece card. The id must use the op_ prefix.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Required | Card ID with op_ prefix. Obtained from /op/search, /op/sets/:setCode, or /op/prices. |
Example Request:
curl -H "X-API-Key: pk_live_your_key_here" \
"https://api.pokewallet.io/op/cards/op_3f8a12c4e9b7d02f..."Response Example:
{
"id": "op_3f8a12c4e9b7d02f...",
"card_number": "OP01-001",
"name": "Roronoa Zoro",
"clean_name": "Roronoa Zoro",
"sub_type_name": "Normal",
"rarity": "L",
"card_type": "Leader",
"ext_color": "Red",
"ext_cost": null,
"ext_power": "5000",
"ext_life": "5",
"ext_subtypes": "Straw Hat Crew;Supernovas",
"ext_attribute": "Slash",
"ext_counterplus": null,
"ext_description": "[DON!! x1] [Activate: Main] ...",
"tcgplayer": {
"url": "https://www.tcgplayer.com/product/...",
"prices": {
"low_price": 1.20,
"market_price": 1.76,
"high_price": 3.50
}
},
"cardmarket": {
"product_name": "Roronoa Zoro (OP01-001)",
"product_url": "https://www.cardmarket.com/...",
"prices": { "avg": 1.64, "low": 0.50, "trend": 1.70 }
}
}Error Codes:
| HTTP | Condition |
|---|---|
400 | ID missing op_ prefix |
400 | Corrupted or undecryptable payload |
404 | Card not found in DB |
group_id < 0): tcgplayer: null, all ext_* fields are null. SP reprints: cards whose card_number belongs to a different set return cardmarket: null to avoid cross-set price collisions. Search Endpoints
/op/searchFull-text search on One Piece card name and card_number.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
q | string | Required | ILIKE %q% on card name and card_number (e.g. zoro, OP01-001) |
page | number | Optional | Page number (default: 1, min: 1) |
limit | number | Optional | Results per page (default: 20, max: 100) |
Example Request:
curl -H "X-API-Key: pk_live_your_key_here" \
"https://api.pokewallet.io/op/search?q=zoro&page=1&limit=20"Response Example:
{
"success": true,
"data": [
{
"id": "op_3f8a12c4e9b7d02f...",
"card_number": "OP01-001",
"name": "Roronoa Zoro",
"sub_type_name": "Normal",
"rarity": "L",
"card_type": "Leader",
"tcgplayer": {
"url": "https://www.tcgplayer.com/product/...",
"prices": { "low_price": 1.20, "market_price": 1.76, "high_price": 3.50 }
},
"cardmarket": {
"product_name": "Roronoa Zoro (OP01-001)",
"product_url": "https://www.cardmarket.com/...",
"prices": { "avg": 1.64, "low": 0.50, "trend": 1.70 }
}
}
],
"total": 12,
"page": 1,
"limit": 20
}d'artagnan) return 0 results due to ILIKE handling of special characters. CM-only cards are not indexed for name search — only TCG cards appear in results. Prices Endpoints
/op/prices?set_code={set_code}PRORaw prices for an entire One Piece set, all variants, no filtering. The set is identified via query parameters — set_code or group_id — not as a path segment. At least one is required.
/op/prices?set_code=OP01 ✓ /op/prices/OP01 ✗ Parameters:
| Parameter | Type | Required | Examples |
|---|---|---|---|
set_code | string | One of these | OP01, EB-01, EB01 (fuzzy → EB-01) |
group_id | number | One of these | 3188, -8 (CM-only set) |
Example Request:
# by set_code (case-insensitive)
curl -H "X-API-Key: pk_live_your_key_here" \
"https://api.pokewallet.io/op/prices?set_code=OP01"
# by group_id (numeric)
curl -H "X-API-Key: pk_live_your_key_here" \
"https://api.pokewallet.io/op/prices?group_id=3188"Response Example:
{
"success": true,
"group_id": "3188",
"total": 159,
"data": [
{
"card_number": "OP01-001",
"name": "Roronoa Zoro (001)",
"variant": "Normal",
"tcgplayer": {
"low_price": 1.20,
"market_price": 1.76,
"high_price": 3.50,
"mid_price": 2.10,
"direct_low_price": 1.50,
"updated_at": "2026-05-14T00:00:00Z"
},
"cardmarket": {
"avg": 1.64,
"low": 0.50,
"trend": 1.70,
"avg1": 1.60,
"avg7": 1.65,
"avg30": 1.70,
"updated_at": "2026-05-14T00:00:00Z"
}
},
{
"card_number": "OP01-001",
"name": "Roronoa Zoro (001) (Foil)",
"variant": "Foil",
"tcgplayer": { "low_price": 3.50, "market_price": 4.20, "high_price": 6.00, "...": "..." },
"cardmarket": { "avg": 3.80, "low": 2.50, "trend": 3.90, "...": "..." }
}
]
}Error Codes:
| HTTP | Condition |
|---|---|
400 | Neither set_code nor group_id provided |
404 | Set not found |
group_id < 0): tcgplayer: null on all cards and variant: null (CM does not expose sub_type_name). The cardmarket object is always present with real prices. One Piece Pro endpoints
Available on Pro, Ultra and Business plans, or during the 7-day trial. Same rules and response format as the Pokémon and other games' endpoints of the same name. Sealed products (booster boxes, packs) are excluded from statistics, completion value and rankings; DON!! cards count as cards.
| Endpoint | What it returns |
|---|---|
GET /op/sets/:set/statistics | Price statistics and rarity breakdown of a set. :set = set code (OP01) or group id. ?variant=normal|foil |
GET /op/sets/:set/completion-value | Cost of one copy of every card in the set, TCGPlayer (USD) and CardMarket (EUR) |
GET /op/sets/trending | Sets whose CardMarket prices moved most: 7-day average against 30-day average, cards from 1 € up. ?period=7d ?limit= (max 50) |
GET /op/analytics/top-cards | Most expensive cards, or fastest-growing on CardMarket. ?metric=price|growth ?source=tcg|cm (growth: cm only) ?limit= (max 100) |
/op/cards/:id/price-history answers 404. Current prices are in /op/cards/:id and /op/prices. Statistics
{
"set_info": {
"name": "Romance Dawn",
"set_code": "OP01",
"set_id": "3188",
"total_cards": 159
},
"price_statistics": {
"tcgplayer": {
"avg_market_price": "53.37",
"min_price": 0.07,
"max_price": 3998.74,
"most_expensive": {
"id": "op_7816ebfb908c6a34cd6feabbf11c84943582bbc7d8109009e47917e7e499e84b245a31a536a5865d5663ccaa201c9f7f",
"name": "Shanks (Parallel) (Manga) (Alternate Art)",
"price": 3998.74
}
},
"cardmarket": {
"avg_price": "59.17",
"min_price": 0.03,
"max_price": 4566.67,
"most_expensive": {
"id": "op_7816ebfb908c6a34cd6feabbf11c84943582bbc7d8109009e47917e7e499e84b245a31a536a5865d5663ccaa201c9f7f",
"name": "Shanks (Parallel) (Manga) (Alternate Art)",
"price": 4566.67
},
"trend_direction": "up"
}
},
"rarity_breakdown": {
"L": 16,
"R": 35,
"UC": 32,
"C": 49,
"SR": 20,
"SEC": 5,
"DON!!": 2
}
}Completion value
{
"set_info": {
"name": "Romance Dawn",
"set_code": "OP01",
"set_id": "3188",
"total_cards": 159
},
"completion_cost": {
"tcgplayer": {
"currency": "USD",
"low_estimate": 7238.83,
"market_estimate": 8485.5,
"high_estimate": 38920.95
},
"cardmarket": {
"currency": "EUR",
"low_estimate": 6489.33,
"avg_estimate": 9408,
"trend_estimate": 9123.63
},
"note": "One copy per card (base finish). TCGPlayer prices in USD, CardMarket prices in EUR. Cross-currency comparison not available."
},
"breakdown_by_rarity": {
"L": {
"count": 16,
"total_cost": 2758.99
},
"R": {
"count": 35,
"total_cost": 567.22
},
"UC": {
"count": 32,
"total_cost": 47.61
},
"C": {
"count": 49,
"total_cost": 21.23
},
"SR": {
"count": 20,
"total_cost": 859.62
},
"SEC": {
"count": 5,
"total_cost": 4225.13
},
"DON!!": {
"count": 2,
"total_cost": 5.7
}
}
}Trending sets (first entry)
{
"period": "7d",
"trending_sets": [
{
"set_name": "Extra Booster: Anime 25th Collection (Japanese)",
"set_code": "EB-02-JP",
"set_id": "-7",
"card_count": 46,
"cardmarket": {
"price_change": "+91.3%",
"avg_price_current": 208.2,
"avg_price_previous": 108.85,
"top_movers": [
{
"name": "Monkey.D.Luffy (OP05-060)",
"change": "+197.9%"
},
{
"name": "Tony Tony.Chopper (OP08-001)",
"change": "+191.2%"
},
{
"name": "Hannyabal (EB01-021)",
"change": "+163.1%"
}
]
},
"tcgplayer": null
}
]
}Top cards by price (first entry)
{
"metric": "price",
"source": "tcg",
"top_cards": [
{
"id": "op_4efc83a71371699af41ffc592c2c1c2076567bcff30c224518260e7ad036150f0156f916c677e9abc3804cefaaf233c9c9",
"card_info": {
"name": "Monkey.D.Luffy (119) (SP) (Gold)",
"clean_name": "Monkey.D.Luffy (119) (SP) (Gold)",
"set_name": "A Fist of Divine Speed",
"set_code": "OP11",
"set_id": "24241",
"card_number": "OP05-119",
"rarity": "SEC",
"card_type": null,
"product_type": "card",
"variants": [
"Foil"
],
"card_text": null
},
"current_price": 13000
}
]
}Images Endpoint
/images/:idReturns card images served via CDN. Use the card's id as the path parameter.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
id | string | Card identifier (e.g. OP01-001) |
Example Request:
curl https://api.pokewallet.io/images/OP01-001 \
-H "X-API-Key: YOUR_API_KEY"image_url field returned by card endpoints to construct the URL directly.Code Examples
JavaScript / Node.js
const API_KEY = 'YOUR_API_KEY';
const BASE_URL = 'https://api.pokewallet.io';
// Fetch all OP sets
const res = await fetch(`${BASE_URL}/op/sets`, {
headers: { 'X-API-Key': API_KEY }
});
const { sets } = await res.json();
// Get a specific set
const setRes = await fetch(`${BASE_URL}/op/sets/OP01`, {
headers: { 'X-API-Key': API_KEY }
});
const setData = await setRes.json();
// Search for a card
const searchRes = await fetch(
`${BASE_URL}/op/search?q=Luffy`,
{ headers: { 'X-API-Key': API_KEY } }
);
const { results } = await searchRes.json();Python
import requests
API_KEY = 'YOUR_API_KEY'
BASE_URL = 'https://api.pokewallet.io'
HEADERS = {'X-API-Key': API_KEY}
# Fetch all OP sets
sets = requests.get(f'{BASE_URL}/op/sets', headers=HEADERS).json()
# Get bulk prices for OP07
prices = requests.get(
f'{BASE_URL}/op/prices',
params={'set_code': 'OP07'},
headers=HEADERS
).json()Error Handling
The API uses standard HTTP status codes to indicate success or failure:
Request successful
Invalid parameters or malformed request
Missing or invalid API key
Paid endpoint without the required plan or an active trial: Pro for Pokémon and One Piece, Ultra for the other games. The body includes redeem_url (trial not activated yet) or upgrade_url (trial expired).
Card, set or image does not exist
The API only accepts GET requests.
/sets/:setCode/image: the set code matches several sets. Retry with ?language= or the numeric set_id.
Rate limit exceeded
Something went wrong on our side
An image could not be fetched from its source. Temporary: retry later.
Errors on game endpoints (/mtg, /ygo, …)
| Status | error | When |
|---|---|---|
| 400 | Invalid or corrupted card ID | ID is neither <game>_… nor 64 hex, or belongs to another game |
| 400 | Query parameter required | q missing, shorter than 2 or longer than 100 characters |
| 400 | Search query rejected | q contains SQL-like text: rephrase it |
| 400 | Invalid or corrupted card ID + did_you_mean | The ID belongs to another game (e.g. a lor_… ID on /mtg/cards): did_you_mean has the right path |
| 404 | Set not found + suggestions | No set with that set_id/set_code. If you wrote the set name, suggestions lists the matching sets with their set_id |
| 404 | Card not found, Image not found | Card or image does not exist |
| 502 | Image not available | Image source temporarily unreachable |
| 503 | Search temporarily unavailable | The search took too long under load. Retry after the seconds in the Retry-After header, or use more specific words |
Error Response Format
Every error has error (short, stable) and message (what to fix). When the API can tell what you meant, did_you_mean contains the corrected path:
// GET /magic/sets
{
"error": "Endpoint not found",
"message": "Did you mean /mtg/sets?",
"did_you_mean": "/mtg/sets",
"docs": "https://pokewallet.io/api-docs"
}Authentication errors (401) also include an example request. A trailing slash is ignored: /sets/ and /sets are the same endpoint.
Best Practices
Use Environment Variables
Never hardcode API keys. Always use environment variables or secure secret management.
Handle Rate Limits Gracefully
Implement exponential backoff when you receive a 429 response. Check rate limit headers to avoid hitting limits.
Cache Results
Cache API responses when appropriate to reduce requests and improve performance.
Use Search Endpoint
Always use /search for the most complete and accurate data.
Monitor Your Usage
Check your dashboard regularly to track API usage and avoid unexpected rate limit hits.
Error Handling
Always implement proper error handling for network failures, rate limits, and invalid responses.
Need Help?
If you have questions or run into issues, we're here to help!