Official Python SDK for CardSight AI REST API
The most comprehensive trading card identification and collection management platform. 12M+ Trading Card Catalog • Baseball, Football, Basketball, Hockey, Pokemon, Magic: The Gathering • AI-Powered Recognition • Free Tier Available
Quick Links:Getting Started • Installation • Examples • API Documentation • Support
- Full Type Safety - Complete type hints with auto-generated types from OpenAPI
- Multi-Card Detection - Identify multiple cards in a single image with confidence scores
- Async & Sync Support - Use asyncio or traditional synchronous code
- Smart Error Handling - Custom exception hierarchy with detailed error information
- Minimal Dependencies - Only essential packages (httpx, attrs, python-dotenv)
- 6M+ Cards - Baseball, Football, and Basketball. Hockey and TCG (Pokemon, Magic: The Gathering, Yu-Gi-Oh!, One Piece) coming soon
- Market Data - Completed-sales pricing (single + bulk), active marketplace listings, and graded population reports
- 100% API Coverage - All CardSight AI endpoints fully implemented
- Auto-Generated - Always up-to-date with the latest API changes
| Feature | Description | Primary Methods |
|---|---|---|
| Card Identification | Identify multiple cards from images using AI | identify.identify() |
| Set Identifiability | Free pre-flight check of which sets AI can identify | card_identification.list_identifiable_sets(), card_identification.check_set_identifiable() |
| Card Detection | Detect cards in images | detect.detect_card() |
| Global Search | Fuzzy search across cards, sets, releases, parallels | catalog.search_catalog(q="...") |
| Catalog Search | Search 12M+ trading cards database | catalog.get_cards(), catalog.get_sets() |
| Flexible Metadata | Browse flexible card fields (HP, Rarity, Artist, etc.) | catalog.get_fields(), catalog.get_field_by_id() |
| Random Catalog | Pack opening simulations with parallel odds | catalog.get_random_cards(), catalog.get_random_sets() |
| Pricing | Completed sales data, raw + graded, single & bulk, title search | pricing.get_card_pricing(), pricing.get_bulk_pricing(), pricing.search_pricing_by_title() |
| Marketplace | Active marketplace listings by grade and type, title search | marketplace.get_card_marketplace(), marketplace.search_marketplace_by_title() |
| Population | Graded population reports by card, set, release | population.get_card_population(), population.get_set_population(), population.get_release_population() |
| Release Calendar | Upcoming & recent product releases | release_calendar.get_release_calendar() |
| Collections | Manage owned card collections with analytics | collections.create_collection(), collections.add_collection_cards() |
| Collectors | Manage collector profiles | collectors.create_collector(), collectors.update_collector() |
| Lists | Track wanted cards (wishlists) | lists.create_list(), lists.add_cards_to_list() |
| Binders | Organize collection subsets | collections.create_binder() |
| Grading | PSA, BGS, SGC grade information | grades.get_grading_companies() |
| AI Search | Natural language queries | ai.process_ai_query() |
| Autocomplete | Search suggestions for all entities | autocomplete.autocomplete_cards() |
- Python 3.10+ (uses modern type hints and async features)
- API Key from cardsight.ai (free tier available)
# pip
pip install cardsightai
# poetry
poetry add cardsightai
# pipenv
pipenv install cardsightaiGet started in minutes with a free API key from cardsight.ai - no credit card required!
fromcardsightaiimportCardSightAI# 1. Initialize the client (auto-detects CARDSIGHTAI_API_KEY env var)client=CardSightAI(api_key='your_api_key_here')
# 2. Identify a card from an imageresult=client.identify.identify('path/to/card.jpg')
# 3. Access the identification resultsifresultandhasattr(result, 'detections'):
# The API can detect multiple cards in a single imagedetection=result.detections[0] ifresult.detectionselseNoneifdetectionanddetection.card:
print(f"Card: {detection.card.name}")
print(f"Confidence: {detection.confidence}") # "High", "Medium", or "Low"print(f"Total cards detected: {len(result.detections)}")Async Version:
importasynciofromcardsightaiimportAsyncCardSightAIasyncdefmain():
asyncwithAsyncCardSightAI() asclient:
result=awaitclient.identify.identify('path/to/card.jpg')
ifresultandhasattr(result, 'detections'):
detection=result.detections[0] ifresult.detectionselseNoneifdetection:
print(f"Card: {detection.card.name}")
asyncio.run(main())That's it! The SDK handles all API communication, type safety, and error handling automatically.
The identification endpoint uses AI to detect trading cards in images. It can identify multiple cards in a single image and returns confidence levels for each detection.
fromcardsightaiimportCardSightAIclient=CardSightAI()
# Identify from file pathresult=client.identify.identify('card_image.jpg')
# Or from byteswithopen('card_image.jpg', 'rb') asf:
result=client.identify.identify(f.read())
# Process resultsfordetectioninresult.detections:
print(f"Card: {detection.card.name}")
print(f"Set: {detection.card.set_name}")
print(f"Confidence: {detection.confidence}")
print(f"Year: {detection.card.year}")
print("---")When a card is inside a graded slab, the API automatically detects the grading company:
result=client.identify.identify('graded_card.jpg')
fordetectioninresult.detections:
ifhasattr(detection, 'grading') anddetection.grading:
print(f"Graded by: {detection.grading.company.name}")
print(f"Grading confidence: {detection.grading.confidence}")Each detection includes:
confidence: "High", "Medium", or "Low"card: Full card details including name, set, year, attributes, pricinggrading: (optional) Slab grading info — company, grade and condition descriptor, qualifier (OC, MC, PD, ST), and autograph grade when card is in a graded slabfields: (optional) Flexible metadata array (e.g., HP, Rarity, Artist, Mana Cost) for cards that expose itnumbered_to: (optional) Print run for numbered base cardssuggestions: (optional) Alternative reprint candidates when the match is ambiguousset: Set informationrelease: Release informationmanufacturer: Manufacturer details
Use the included utility function to get the best match. Note that get_highest_confidence_detection works with dict-style data — convert response objects as needed:
fromcardsightaiimportCardSightAIfromcardsightai.extrasimportget_highest_confidence_detectionclient=CardSightAI()
result=client.identify.identify('card.jpg')
# get_highest_confidence_detection works with dicts/lists of dicts# If your result is an attrs response object, access detections directly:ifresultandhasattr(result, 'detections') andresult.detections:
best=result.detections[0] # Already sorted by confidence from the APIprint(f"Best match: {best.card.name} ({best.confidence})")Search and browse the comprehensive card catalog:
fromcardsightaiimportCardSightAIclient=CardSightAI()
# Get catalog statisticsstats=client.catalog.get_statistics()
print(f"Total cards: {stats.cards.total:,}")
print(f"Total sets: {stats.sets.total:,}")
print(f"Total releases: {stats.releases.total:,}")
# List segments (Sports, Entertainment, Gaming)segments=client.catalog.get_segments()
forsegmentinsegments.segments:
print(f"Segment: {segment.name}")
# List manufacturersmanufacturers=client.catalog.get_manufacturers()
formanufacturerinmanufacturers.manufacturers[:10]:
print(f"Manufacturer: {manufacturer.name}")
# Search releases with paginationreleases=client.catalog.get_releases(
take=20,
skip=0,
sort='year',
order='desc'
)
# Get specific card detailscard=client.catalog.get_card(id='card-uuid-here')
print(f"Card: {card.name}")
print(f"Raw price: ${card.prices.raw}")
print(f"PSA 10 price: ${card.prices.psa_10}")Search across cards, sets, releases, and parallels with fuzzy matching:
fromcardsightaiimportCardSightAIclient=CardSightAI()
# Basic searchresults=client.catalog.search_catalog(q="Mike Trout", take=10)
forresultinresults.results:
print(f"{result.type_}: {result.name} (relevance: {result.relevance})")
# Filter by typefromcardsightai.generated.card_sight_ai_api_client.modelsimportSearchCatalogTyperesults=client.catalog.search_catalog(q="Topps Chrome", type_=SearchCatalogType.SET)
# Filter by year rangeresults=client.catalog.search_catalog(q="rookie", min_year="2020", max_year="2024")Simulate pack opening with weighted odds:
fromcardsightaiimportCardSightAIclient=CardSightAI()
# Get random cards (like opening a pack)random_cards=client.catalog.get_random_cards(take=10)
forcardinrandom_cards.cards:
print(f"Pulled: {card.name} - ${card.prices.raw}")
# Get random releaserandom_release=client.catalog.get_random_releases()
print(f"Release: {random_release.name} ({random_release.year})")
# Get random setrandom_set=client.catalog.get_random_sets()
print(f"Set: {random_set.name}")Manage your card collections with full CRUD operations:
fromcardsightaiimportCardSightAIclient=CardSightAI()
# Create a collectioncollection=client.collections.create_collection(name="My Baseball Cards")
# Add cards to collectionclient.collections.add_collection_cards(
collection_id=collection.id,
card_id='card-uuid',
quantity=1,
condition='Near Mint',
purchase_price=50.00,
purchase_date='2024-01-15'
)
# Get collection analyticsanalytics=client.collections.get_collection_analytics(collection_id=collection.id)
print(f"Total value: ${analytics.total_value}")
print(f"Total cards: {analytics.total_cards}")
# List all cards in collectioncards=client.collections.get_collection_cards(collection_id=collection.id)Organize collections into binders:
fromcardsightaiimportCardSightAIclient=CardSightAI()
# Create a binder within a collectionbinder=client.collections.create_binder(
collection_id='collection-uuid',
name='Rookie Cards',
description='All my rookie cards'
)
# Add cards to binderclient.collections.add_card_to_binder(
collection_id='collection-uuid',
binder_id=binder.id,
card_id='card-uuid'
)Track cards you want to acquire:
fromcardsightaiimportCardSightAIclient=CardSightAI()
# Create a want listwant_list=client.lists.create_list(name="Cards I Want")
# Add cards to the listclient.lists.add_cards_to_list(
list_id=want_list.id,
card_id='card-uuid',
max_price=100.00
)
# View your want listcards=client.lists.get_list_cards(list_id=want_list.id)Access grading company data:
fromcardsightaiimportCardSightAIclient=CardSightAI()
# List grading companiescompanies=client.grades.get_grading_companies()
forcompanyincompanies:
print(f"Company: {company.name}")
# Get grade types for a companytypes=client.grades.get_grading_types(company_id='psa-uuid')
# Get specific gradesgrades=client.grades.get_grades(
company_id='psa-uuid',
type_id='numeric-uuid'
)Use natural language to search the catalog:
fromcardsightaiimportCardSightAIclient=CardSightAI()
# Natural language queryresults=client.ai.process_ai_query("Find me Mickey Mantle rookie cards")
forresultinresults:
print(f"Found: {result.card.name}")Get search suggestions for improved UX:
fromcardsightaiimportCardSightAIclient=CardSightAI()
# Autocomplete for cardssuggestions=client.autocomplete.autocomplete_cards(query="Mike Trout")
# Autocomplete for manufacturersmanufacturers=client.autocomplete.autocomplete_manufacturers(query="Top")
# Autocomplete for setssets=client.autocomplete.autocomplete_sets(query="Chrome")Get card images from the catalog:
fromcardsightaiimportCardSightAIclient=CardSightAI()
# Get card imageimage=client.images.get_card_image(card_id='card-uuid')Submit feedback to improve the platform:
fromcardsightaiimportCardSightAIclient=CardSightAI()
# Submit feedback on a card identificationclient.feedback.submit_identify_feedback(
identification_id='id-uuid',
feedback='Incorrect card identified',
correct_card_id='actual-card-uuid'
)
# Submit general feedbackclient.feedback.submit_general_feedback(
feedback='Great API!',
category='positive'
)Before spending an identification call, check for free which sets the AI can identify:
fromcardsightaiimportCardSightAIclient=CardSightAI()
# List all AI-identifiable sets (free, paginated)sets=client.card_identification.list_identifiable_sets(take=20, skip=0)
forsinsets.sets:
print(f"Identifiable: {s.year}{s.release_name}{s.set_name}")
# Verify a specific set is identifiablecheck=client.card_identification.check_set_identifiable(set_id='set-uuid')
print(f"Identifiable: {check.is_identifiable}")Browse the flexible metadata fields used across trading card games (HP, Rarity, Artist, Mana Cost, etc.) with usage counts:
fromcardsightaiimportCardSightAIclient=CardSightAI()
# List flexible metadata fields with usage countsfields=client.catalog.get_fields(take=20, skip=0)
forfieldinfields.fields:
print(f"{field.name} ({field.key}): used {field.usage_count} times")
# Get details for a single fieldfield=client.catalog.get_field_by_id(id='field-key')
print(f"Field: {field.name}")Retrieve historical completed-sales data, grouped into raw (ungraded) and graded sections:
fromcardsightaiimportCardSightAIclient=CardSightAI()
# Pricing for a single card (filter by parallel, grade, period, listing type)pricing=client.pricing.get_card_pricing(
card_id='card-uuid',
period='1y', # all, 30d, 90d, 1y, 5ylimit=50,
)
print(f"Raw sales: {len(pricing.raw.records)}")
forcompanyinpricing.graded:
print(f"Graded by {company.company_name}: {len(company.grades)} grade buckets")
# Bulk pricing for up to 100 cards in one requestfromcardsightai.generated.card_sight_ai_api_client.modelsimportBulkPricingRequestInputbulk=client.pricing.get_bulk_pricing(
body=BulkPricingRequestInput(card_ids=['card-1', 'card-2', 'card-3'])
)
forresultinbulk.results:
print(result)
# Fuzzy free-text search over historical pricing by listing titleresults=client.pricing.search_pricing_by_title(
q='2018 Bowman Chrome Juan Soto PSA 10',
period='all', # all, 30d, 90d, 1y, 5ylimit=25,
)
print(f"Matched {results.meta.total_records} records")
forrecordinresults.results:
print(f"{record.price} — {record.title} ({record.source})")
# Optionally filter by listing type (auction vs. fixed-price)fromcardsightai.generated.card_sight_ai_api_client.modelsimportSearchPricingByTitleListingTypeauctions=client.pricing.search_pricing_by_title(
q='2018 Bowman Chrome Juan Soto PSA 10',
listing_type=SearchPricingByTitleListingType.AUCTION, # auction, fixed, both
)Retrieve current active listings for a card, grouped by grading company and grade:
fromcardsightaiimportCardSightAIclient=CardSightAI()
listings=client.marketplace.get_card_marketplace(
card_id='card-uuid',
grade_id='grade-uuid', # optionallimit=25,
)
print(f"Raw listings: {len(listings.raw.records)}")
forcompanyinlistings.graded:
print(f"{company.company_name}: {len(company.grades)} grade groups")
# Fuzzy free-text search over active marketplace listings by titleresults=client.marketplace.search_marketplace_by_title(
q='2018 Bowman Chrome Juan Soto PSA 10',
limit=25,
)
print(f"Matched {results.meta.total_records} active listings")
forrecordinresults.results:
print(f"{record.title} — {record.price} ({record.source})")Get graded population counts for a single card, an entire set, or a release:
fromcardsightaiimportCardSightAIclient=CardSightAI()
# Population for a single card (optionally scope to one grading company)card_pop=client.population.get_card_population(card_id='card-uuid')
print(f"{card_pop.card_name}: {card_pop.total_population} graded copies")
# Population across an entire setset_pop=client.population.get_set_population(set_id='set-uuid')
# Population across a releaserelease_pop=client.population.get_release_population(release_id='release-uuid')Browse upcoming and recent product releases, filtered by segment, manufacturer, or year:
fromcardsightaiimportCardSightAIclient=CardSightAI()
calendar=client.release_calendar.get_release_calendar(
take=20,
skip=0,
year='2026',
segment='baseball', # UUID or case-insensitive name
)
forentryincalendar.release_calendar:
print(f"{entry.release_date}: {entry.name}")The SDK provides full async support with AsyncCardSightAI:
importasynciofromcardsightaiimportAsyncCardSightAIasyncdefmain():
asyncwithAsyncCardSightAI() asclient:
# All methods are asyncstats=awaitclient.catalog.get_statistics()
print(f"Total cards: {stats.cards.total:,}")
segments=awaitclient.catalog.get_segments()
forsegmentinsegments.segments:
print(f"Segment: {segment.name}")
# Concurrent requestsresults=awaitasyncio.gather(
client.catalog.get_cards(take=10),
client.catalog.get_sets(take=10),
client.catalog.get_releases(take=10)
)
asyncio.run(main())The SDK includes complete type hints for excellent IDE support:
fromcardsightaiimportCardSightAIfromcardsightai.generated.card_sight_ai_api_client.modelsimport (
GetV1CatalogCardsResponse200,
GetV1CatalogStatisticsResponse200
)
client=CardSightAI()
# Full type inferencestats: GetV1CatalogStatisticsResponse200=client.catalog.get_statistics()
cards: GetV1CatalogCardsResponse200=client.catalog.get_cards()Response models for the newer endpoints are available too, e.g. PricingResponse,
BulkPricingResponse, MarketplaceResponse, CardPopulationResponse,
SetPopulationResponse, ReleasePopulationResponse, PaginatedReleaseCalendarResponse,
PaginatedFieldsResponse, DetailedFieldResponse, IdentifiableSetsResponse, and
SetIdentifiableResponse — all importable from
cardsightai.generated.card_sight_ai_api_client.models.
The SDK defines custom exception classes for structured error handling:
fromcardsightaiimportCardSightAIfromcardsightai.exceptionsimport (
CardSightAIError,
AuthenticationError,
RateLimitError,
APIError
)
client=CardSightAI()
try:
result=client.identify.identify('card.jpg')
exceptAuthenticationErrorase:
print(f"Invalid API key: {e.message}")
exceptRateLimitErrorase:
print(f"Rate limit exceeded. Retry after {e.retry_after} seconds")
exceptAPIErrorase:
print(f"API error ({e.status_code}): {e.message}")
print(f"Request ID: {e.request_id}")
exceptCardSightAIErrorase:
print(f"General error: {e.message}")Note: The current SDK passes through response objects from the generated client layer. HTTP errors are returned as typed error response objects rather than raised as exceptions. The exception classes above are available for use in your own error-handling logic or for future SDK versions that may raise them automatically.
Customize client behavior:
fromcardsightaiimportCardSightAIclient=CardSightAI(
api_key='your_api_key', # Or use CARDSIGHTAI_API_KEY env varbase_url='https://api.cardsight.ai', # Defaulttimeout=30.0, # Request timeout in seconds
)The SDK supports environment variables for configuration:
# Requiredexport CARDSIGHTAI_API_KEY='your_api_key_here'# Optional overridesexport CARDSIGHTAI_BASE_URL='https://api.cardsight.ai'export CARDSIGHTAI_TIMEOUT='30'Then initialize without parameters:
fromcardsightaiimportCardSightAI# Automatically uses CARDSIGHTAI_API_KEYclient=CardSightAI()The SDK provides complete coverage of all CardSight AI endpoints:
| Category | Endpoints | Status |
|---|---|---|
| Card Identification | POST /v1/identify/card/{set}, POST /v1/identify/card/segment/{segment} | ✅ |
| Set Identifiability | GET /v1/identify/list/sets, GET /v1/identify/check/set/{set_id} | ✅ |
| Card Detection | POST /v1/identify/card/detect | ✅ |
| Global Search | GET /v1/catalog/search - fuzzy search across all entities | ✅ |
| Catalog | Statistics, Segments, Manufacturers, Releases, Sets, Cards, Parallels, Attributes | ✅ |
| Catalog Fields | GET /v1/catalog/fields, GET /v1/catalog/fields/{id} | ✅ |
| Random Catalog | Random cards, sets, releases | ✅ |
| Pricing | GET /v1/pricing/{card_id}, POST /v1/pricing/ (bulk), GET /v1/pricing/search (title search) | ✅ |
| Marketplace | GET /v1/marketplace/{card_id}, GET /v1/marketplace/search (title search) | ✅ |
| Population | GET /v1/population/card/{id}, /set/{id}, /release/{id} | ✅ |
| Release Calendar | GET /v1/release-calendar/ | ✅ |
| Collections | Full CRUD, analytics, breakdown, cards | ✅ |
| Binders | Create, update, delete, cards | ✅ |
| Lists | Create, update, delete, cards | ✅ |
| Collectors | Create, update, delete | ✅ |
| Grading | Companies, types, grades | ✅ |
| AI Search | Natural language queries | ✅ |
| Autocomplete | Cards, sets, releases, manufacturers, segments, years | ✅ |
| Images | Card image retrieval | ✅ |
| Feedback | Identification, general, entity feedback | ✅ |
| Subscription | Subscription management | ✅ |
| Health | API health check (public + authenticated) | ✅ |
# Clone the repository
git clone https://github.com/CardSightAI/cardsightai-sdk-python.git
cd cardsightai-sdk-python
# Install dependencies
poetry install
# Run tests
poetry run pytest
# Build package
poetry buildThe SDK auto-generates from the OpenAPI specification:
# Regenerate client code
make regenerate
# Or manually
poetry run python scripts/generate_client.py# Run all tests
make test# Run specific tests
poetry run pytest tests/unit/
# Run with coverage
poetry run pytest --cov=cardsightai --cov-report=html# Lint code
make lint
# Format code
make format
# Type check
poetry run mypy cardsightai/The SDK supports Python 3.10 and later. We test against:
- Python 3.10
- Python 3.11
- Python 3.12
The SDK has minimal runtime dependencies:
httpx- Modern HTTP client with async supportattrs- Python classes without boilerplatepython-dateutil- Date/time utilitiespython-dotenv- Environment variable managementtyping-extensions- Backported type hints
- Documentation: api.cardsight.ai/documentation
- Issues: GitHub Issues
- Email: support@cardsight.ai
- Discord: Join our community
This SDK is released under the MIT License.
We welcome contributions! Please see our Contributing Guide for details.
See CHANGELOG.md for release history and changes.
Made with love by CardSight AI, Inc.