API Reference
Programmatic access for Vendor-tier subscribers. Pull live Cardmarket prices, manage portfolios and identify cards from scripts, spreadsheets or your own backend.
Quick start
Three steps:
- Subscribe to the Vendor plan.
- In the app drawer, open
π API keysβ click+ New key. Copy it immediately β keys are shown only once. - Send the key as
Authorization: Bearer <key>with every request.
Base URL:
https://www.pokeprovs-ink.com
First request:
curl -H "Authorization: Bearer pp_live_β¦" \
https://www.pokeprovs-ink.com/api/me
Returns your account info, current tier and usage counters.
Authentication
All API requests require an Authorization: Bearer pp_live_β¦ header.
Keys start with pp_live_ and are tied to a single account.
- Keys only work while your account is on the Vendor tier (or admin). Downgrading silently disables all keys.
- Keys are stored as SHA-256 hashes β we cannot recover a lost key. Generate a new one.
- Revoke any key from the drawer's
API keysdialog. Revocation is instant.
If a redirect drops your Authorization header (some HTTP clients strip it
on cross-host redirects), use the canonical https://www.pokeprovs-ink.com
URL directly.
Portfolios
List portfolios
GET /api/portfolios
{
"portfolios": [
{ "id": 1, "name": "Default", "created_at": "2026-01-15T10:30:00+00:00" },
{ "id": 2, "name": "Shop inventory", "created_at": "2026-04-02T14:12:00+00:00" }
]
}
Create / rename / delete a portfolio
POST /api/portfolios { "name": "Shop inventory" }
PATCH /api/portfolios/{id} { "name": "New name" }
DELETE /api/portfolios/{id}
Form-encoded or multipart bodies. The last remaining portfolio cannot be deleted.
List items in a portfolio
GET /api/portfolio # default portfolio
GET /api/portfolio?portfolio_id=2 # specific portfolio
Returns split open / sold sections with totals and live prices:
{
"open": {
"items": [{ "id": 1, "card_code": "PFL 125", "naam": "β¦", "inkoop": 300.0, "current_price": 880.0, β¦ }],
"totaal_inkoop": 300.0,
"totaal_waarde": 880.0,
"pl": 580.0,
"pl_pct": 193.3
},
"sold": { "items": [], "totaal_inkoop": 0, "totaal_verkoop": 0, "realized": 0, "realized_pct": 0 }
}
Add a card
POST /api/portfolio
input=PFL125 # card code
inkoop=300.00 # buy-in price
portfolio_id=2 # optional, defaults to the user's first portfolio
Mark sold / reopen / delete an item
POST /api/portfolio/{id}/sell verkoop_prijs=880.00
POST /api/portfolio/{id}/reopen
DELETE /api/portfolio/{id}
Export / import CSV
GET /api/portfolio/export?portfolio_id=2 # text/csv response
POST /api/portfolio/import # multipart: file=<csv> portfolio_id=2
Card lookup
GET /api/card?input=163/086
GET /api/card?input=163/086&grade=PSA10
Returns either a single card payload (with margins, eBay slab data,
Cardmarket-URLs) or β when the input is ambiguous β a list of options
across multiple sets:
{
"type": "ambiguous",
"card_number": "163",
"options": [
{ "setcode": "WHT", "name": "β¦", "set_name": "White Flare", "released_at": "2025-β¦", "input": "WHT163" },
β¦
]
}
Photo identify
POST /api/identify
Content-Type: multipart/form-data
photo=<jpg or png>
Returns the recognized card + price payload. Counts against your monthly photo quota (unlimited on Pro Trader / Vendor).
Bulk pricing
POST /api/bulk
codes=WHT163\nPR-SV85\n163/086
Returns each card with its current Cardmarket price and 70/75/80/85/90 % buy-in margins. Skips rows that don't resolve.
Trends
GET /api/trends?period=7d&direction=up
GET /api/trends?period=30d&direction=down
Top 15 risers / fallers based on Cardmarket 7- or 30-day price change.
Account info
GET /api/me
Returns email, tier, tier limits, current usage counters, trial-end date and Stripe customer status. Useful for sanity-checking auth before doing real work.
Errors & quotas
401 Unauthorizedβ missing or invalidAuthorizationheader. Wrong key prefix, revoked key, or non-Vendor tier.402 Payment Requiredβ quota exhausted (e.g. monthly photo limit). Upgrade your tier and retry.403 Forbiddenβ endpoint not allowed for your tier (e.g. POST/api/portfoliosrequires Vendor).404 Not Foundβ card / portfolio / item not in the catalogue.5xxβ transient. Retry with exponential backoff.
All error responses are JSON: { "detail": "human-readable message" }.
Code examples
cURL
curl -H "Authorization: Bearer $POKEPROVS_KEY" \
https://www.pokeprovs-ink.com/api/portfolio
PowerShell
$h = @{ Authorization = "Bearer $env:POKEPROVS_KEY" }
Invoke-RestMethod -Uri "https://www.pokeprovs-ink.com/api/portfolio" -Headers $h
Python
import os, requests
key = os.environ["POKEPROVS_KEY"]
r = requests.get(
"https://www.pokeprovs-ink.com/api/portfolio",
headers={"Authorization": f"Bearer {key}"},
timeout=15,
)
r.raise_for_status()
print(r.json())
Add a card from a script
import requests
requests.post(
"https://www.pokeprovs-ink.com/api/portfolio",
headers={"Authorization": f"Bearer {key}"},
data={"input": "WHT163", "inkoop": 12.50, "portfolio_id": 2},
).raise_for_status()
Support
API issues, integration questions or feature requests: send us an email at support@pokeprovs-ink.com. Vendor subscribers get priority support.