Official Java SDK for CardSight AI REST API
The most comprehensive trading card identification and collection management platform. 12M+ Cards • AI-Powered Recognition • Free Tier Available
Quick Links:Why CardSight AI? • Getting Started • Installation • Examples • API Documentation • Support
Building a trading card app means solving two hard problems before you can ship a single feature: recognizing cards from a photo and maintaining an accurate catalog of every card ever printed. CardSight AI does both, so you can build your product instead of a computer-vision pipeline and a data-entry team.
- One photo, full identification. A single AI scan identifies multiple cards at once — including the exact parallel/variant, the print run for numbered cards, and the grade on a slabbed card. Point a camera at a card and get structured data back.
- A catalog that spans the whole hobby. 12M+ cards across sports (baseball, football, basketball, and more) and trading card games (Pokémon, Magic: The Gathering, Yu-Gi-Oh!, and beyond) — one API instead of stitching together a different data source per category.
- Real market data, built in. Completed-sale pricing, active marketplace listings, and graded population reports power "what's it worth", portfolio tracking, and deal-finding features without integrating a second vendor.
- Collection management out of the box. Collections, binders, want lists, and analytics are first-class endpoints — skip building your own card database and CRUD layer.
- One integration works across every game. Flexible metadata (HP, Rarity, Artist, Mana Cost, …) is exposed uniformly through the Fields system, so supporting a new game doesn't mean new code.
- Free to start, fast to integrate. A free tier, a strongly typed SDK, and auto-generation from our OpenAPI spec mean you're making real calls in minutes — and staying in sync automatically as the API grows.
Perfect for building: card scanner & identification apps, collection trackers, trading-card marketplaces, price guides and valuation dashboards, breaking / pack-opening tools, and grading & population lookups.
- Auto-Generated from OpenAPI - Always up-to-date with the latest API; every endpoint is available with zero manual wrapper code
- Full Type Safety - Strongly typed request parameters and response models for every endpoint
- Multi-Card Detection - Identify multiple cards in a single image with per-detection confidence levels
- Flexible Metadata via Fields - Search and surface arbitrary card properties (HP, Rarity, Artist, Mana Cost, etc.) across any trading card game
- Dependency Injection Ready - Built-in Jakarta Inject (JSR-330) annotations for Spring, CDI, and Guice
- Robust HTTP Stack - Built on OkHttp with Gson serialization, connection pooling, and configurable timeouts
- Full API Coverage - All CardSight AI endpoints, grouped into typed API categories
| Feature | Description | Primary Methods |
|---|---|---|
| Card Identification | Identify multiple cards from images using AI; free pre-flight set identifiability lookups | cardIdentification().identifyCard(), identifyCardBySegment(), listIdentifiableSets(), checkSetIdentifiable() |
| Card Detection | Check if trading cards are present in an image | detection().detectCard() |
| Catalog Search | Fuzzy search across cards, sets, releases, parallels | catalog().searchCatalog(), catalog().getCards() |
| Random Catalog | Pack-opening simulations with parallel odds | catalog().getRandomCards(), catalog().getRandomSets() |
| Collections | Manage owned card collections with analytics | collections().createCollection(), addCollectionCards() |
| Collectors | Manage collector profiles | collectors().createCollector(), updateCollector() |
| Lists | Track wanted cards (wishlists) | lists().createList(), addCardsToList() |
| Binders | Organize collection subsets | collections().createBinder() |
| Pricing | Completed sales data for cards; free-text title search | pricing().getCardPricing(), getBulkPricing(), searchPricingByTitle() |
| Marketplace | Active marketplace listings for cards; free-text title search | marketplace().getCardMarketplace(), searchMarketplaceByTitle() |
| Population Reports | Graded population counts by card, set, or release | population().getCardPopulation(), getSetPopulation(), getReleasePopulation() |
| Grading | PSA, TAG, BGS, SGC grade information | grading().getGradingCompanies() |
| AI Search | Natural language queries | ai().processAIQuery() |
| Autocomplete | Search suggestions for all entities | autocomplete().autocompleteCards() |
| Field Catalog | Browse flexible metadata fields (Artist, HP, Rarity, etc.) | catalog().getFields(), getFieldById() |
| Release Calendar | Upcoming and recent card product releases | releaseCalendar().getReleaseCalendar() |
- Java 21 or higher (LTS)
- Maven 3.6+ or Gradle
- API Key from cardsight.ai (free tier available)
<dependency>
<groupId>ai.cardsight</groupId>
<artifactId>cardsightai-sdk-java</artifactId>
<version>2.0.0</version>
</dependency>implementation 'ai.cardsight:cardsightai-sdk-java:2.0.0'Get started in minutes with a free API key from cardsight.ai - no credit card required!
importai.cardsight.CardSightAI;
importai.cardsight.generated.model.IdentifyCardResponse;
importjava.io.File;
publicclassQuickStart {
publicstaticvoidmain(String[] args) throwsException {
// 1. Initialize the client (or use the CARDSIGHTAI_API_KEY env var)CardSightAIclient = newCardSightAI("your_api_key_here");
// 2. Identify a card from an imageIdentifyCardResponseresult = client.cardIdentification()
.identifyCard(newFile("card.jpg"));
// 3. Access the identification resultsif (Boolean.TRUE.equals(result.getSuccess()) && !result.getDetections().isEmpty()) {
vardetection = result.getDetections().get(0); // best match firstvarcard = detection.getCard();
System.out.println("Card: " + card.getName()); // exact match onlySystem.out.println("Set: " + card.getReleaseName()); // exact + set-level matchSystem.out.println("Confidence: " + detection.getConfidence()); // High / Medium / LowSystem.out.println("Total cards detected: " + result.getDetections().size());
}
}
}That's it! The SDK handles all API communication, serialization, and type mapping automatically. Every API method throws a checked ApiException on a non-2xx response (see Error Handling).
Each API category is reached through a typed accessor on the client (client.catalog(), client.pricing(), etc.). Each accessor returns the generated API class for that category.
The identification endpoint uses AI to detect cards in images. It can identify multiple cards in a single image and returns a confidence level for each detection. Use identifyCard() for the default segment (baseball) or identifyCardBySegment() to target a specific sport/game.
importai.cardsight.CardSightAI;
importai.cardsight.generated.model.IdentificationData;
importai.cardsight.generated.model.IdentifyCardResponse;
importjava.io.File;
CardSightAIclient = newCardSightAI("your_api_key");
IdentifyCardResponseresult = client.cardIdentification().identifyCard(newFile("card.jpg"));
if (Boolean.TRUE.equals(result.getSuccess())) {
if (result.getDetections().isEmpty()) {
System.out.println("No cards detected in image");
return;
}
System.out.println("Detected " + result.getDetections().size() + " card(s)");
for (IdentificationDatadetection : result.getDetections()) {
System.out.println("\nConfidence: " + detection.getConfidence());
varcard = detection.getCard();
if (card != null && card.getId() != null) {
// Exact match — all fields populatedSystem.out.println(" Name: " + card.getName());
System.out.println(" Year: " + card.getYear());
System.out.println(" Manufacturer: " + card.getManufacturer());
System.out.println(" Set: " + card.getCardSetName());
System.out.println(" Number: " + card.getNumber());
System.out.println(" Card ID: " + card.getId());
} elseif (card != null && card.getCardSetId() != null) {
// Set-level match — no specific card, but set info availableSystem.out.println(" Release: " + card.getReleaseName());
System.out.println(" Set: " + card.getCardSetName());
System.out.println(" Year: " + card.getYear());
} else {
// No match — a card was detected but not identifiedSystem.out.println(" Could not identify this card");
}
}
// Request metadataSystem.out.println("\nRequest ID: " + result.getRequestId());
System.out.println("Processing time: " + result.getProcessingTime() + "ms");
// Server advisory messages (e.g. image-quality warnings)if (result.getMessages() != null) {
result.getMessages().forEach(m ->
System.out.println("[" + m.getType() + "] " + m.getMessage()));
}
}
// Segment-specific identification (football, basketball, magic, etc.)IdentifyCardResponsefootball = client.cardIdentification()
.identifyCardBySegment("football", newFile("card.jpg"));Note:
identifyCard/identifyCardBySegmentaccept ajava.io.File. If your image is in memory, write it to a temporary file first (e.g.Files.write(...)).
Each detection has a confidence level and a card object. The card fields are populated based on the match level:
- Exact match:
card.getId()is non-null — all fields populated, includinggetNumber()and optionallygetParallel() - Set-level match:
card.getCardSetId()is non-null butgetId()is null — release/set info available but no specific card - No match: the card's fields are all null — a card was detected in the image but couldn't be identified
Detections may also include grading information via detection.getGrading() when the card is inside a graded slab (see Grading / Slab Detection).
The response models are plain Java objects, so use standard streams to filter and group detections:
importai.cardsight.generated.model.IdentificationData;
// Highest-confidence (best) matchvarbest = result.getDetections().stream().findFirst().orElse(null);
// Only high-confidence detectionsvarhighConfidence = result.getDetections().stream()
.filter(d -> d.getConfidence() == IdentificationData.ConfidenceEnum.HIGH)
.toList();
// Only exact matches (detections with a card ID)varexactMatches = result.getDetections().stream()
.filter(d -> d.getCard() != null && d.getCard().getId() != null)
.toList();Before spending a billed identify call, you can confirm whether a set is supported. These endpoints are free — they do not count toward your billed API usage.
// List every set the system can identify (paginated)varsets = client.cardIdentification().listIdentifiableSets(20, 0); // take, skipSystem.out.println(sets.getTotalCount() + " identifiable sets");
// Check whether a specific set is identifiable by its set IDvarcheck = client.cardIdentification().checkSetIdentifiable("set_uuid");
if (Boolean.TRUE.equals(check.getIsIdentifiable())) {
System.out.println("Set is identifiable");
}Every detected card can also carry:
getNumberedTo()— print run for numbered base cards (e.g.25for a/25), independent of parallelsgetFields()— aList<FieldValue>of key/value metadata tailored to the TCG (e.g.HP,RARITY,ARTIST,MANA_COST)getSuggestions()— alternative card candidates when multiple reprints scored similarly
vardetection = result.getDetections().get(0);
varcard = detection.getCard();
// Iterate flexible metadataif (card.getFields() != null) {
card.getFields().forEach(f -> System.out.println(f.getKey() + ": " + f.getValue()));
// e.g. "HP: 120", "RARITY: Holo Rare", "ARTIST: Mitsuhiro Arita"
}
// Base-card print run (distinct from parallel print runs)if (card.getNumberedTo() != null) {
System.out.println("Limited to /" + card.getNumberedTo());
}
// Alternative matches when reprints score similarlyif (card.getSuggestions() != null) {
card.getSuggestions().forEach(alt ->
System.out.println("Could also be: " + alt.getCardSetName()));
}The identify endpoint can detect parallel variants (Refractors, Prizms, numbered parallels, etc.). When a parallel is detected, card.getParallel() returns a ParallelSummary:
varcard = detection.getCard();
if (card.getParallel() != null) {
varparallel = card.getParallel();
System.out.println("Parallel: " + parallel.getName()); // e.g. "Gold Refractor"System.out.println("Parallel ID: " + parallel.getId());
if (parallel.getDescription() != null) {
System.out.println("Description: " + parallel.getDescription());
}
// Numbered parallel (limited print run)if (parallel.getNumberedTo() != null) {
System.out.println("NUMBERED: only " + parallel.getNumberedTo() + " exist!");
}
} else {
System.out.println("Base card");
}When identifying a card inside a graded slab, detection.getGrading() returns a SlabGradingDetail:
vargrading = detection.getGrading();
if (grading != null) {
System.out.println("Slab detection confidence: " + grading.getConfidence());
// Structured slab data (each may be null depending on what was read from the label):// grading.getCompany() -> SlabCompany (e.g. PSA, BGS, SGC)// grading.getGrade() -> SlabGrade (grade value + condition)// grading.getQualifier() -> SlabQualifier (defect qualifier, e.g. OC, MC, PD, ST)// grading.getAutoGrade() -> SlabAutoGrade (autograph grade)
}The detection endpoint is a lightweight alternative to full identification — it checks whether trading cards are present in an image without identifying them. This is faster and cheaper when you only need to know if cards exist in the image.
importai.cardsight.generated.model.DetectCardResponse;
importjava.io.File;
DetectCardResponseresult = client.detection().detectCard(newFile("image.jpg"));
System.out.println("Cards detected: " + result.getDetected()); // true / falseSystem.out.println("Number of cards: " + result.getCount()); // 0, 1, 2, ...if (result.getMessages() != null) {
result.getMessages().forEach(m ->
System.out.println("[" + m.getType() + "] " + m.getMessage()));
}Search across cards, sets, releases, and parallels with a single query:
importai.cardsight.generated.model.CatalogSearchResponse;
// Global fuzzy search:// q, take, skip, type, segment, manufacturer, year, minYear, maxYear, fieldCatalogSearchResponseresults = client.catalog()
.searchCatalog("Ken Griffey Jr", 10, 0, null, null, null, null, null, null, null);
// Filter by entity type ('card' | 'set' | 'release' | 'parallel') and yearvarsetResults = client.catalog()
.searchCatalog("Topps Chrome", 10, 0, "set", null, null, "2023", null, null, null);
System.out.println("Found " + results.getTotalCount() + " results");
results.getResults().forEach(r -> {
System.out.println("[" + r.getType() + "] " + r.getName() + " (relevance: " + r.getRelevance() + ")");
if (r.getCardSetName() != null) System.out.println(" Set: " + r.getCardSetName());
if (r.getYear() != null) System.out.println(" Year: " + r.getYear());
});Every trading card game has different metadata: Pokémon cards have HP and Rarity, Magic: The Gathering cards have Mana Cost and Artist, Yu-Gi-Oh! cards have Attribute and Level. Rather than hard-coding columns per game, CardSight exposes a flexible Fields system — any card, set, release, or segment can carry key/value metadata, and the catalog exposes it as a first-class browsable entity.
Browse available fields:
// take, skip, name, key, sort, ordervarfields = client.catalog().getFields(20, 0, null, null, "usageCount", "desc");
fields.getFields().forEach(f ->
System.out.println(f.getName() + " (" + f.getKey() + ")"));Surface metadata directly from an identification result — every detected card includes a getFields() array:
importai.cardsight.generated.model.IdentifyCardResponse;
IdentifyCardResponseresult = client.cardIdentification()
.identifyCardBySegment("magic", newFile("mtg-card.jpg"));
varcard = result.getDetections().get(0).getCard();
if (card.getFields() != null) {
for (varfield : card.getFields()) {
if ("ARTIST".equalsIgnoreCase(field.getKey())) {
System.out.println(card.getName() + " by " + field.getValue());
}
}
}Get completed sales pricing for a card, grouped into raw (ungraded) and graded sections:
importai.cardsight.generated.model.PricingResponse;
// cardId, parallelId, gradeId, period, listingType, limit// period: "7d", "2w", "3m", "1y", "all" listingType: "auction", "fixed", "both"PricingResponsepricing = client.pricing()
.getCardPricing("card_uuid", null, null, "90d", "both", 50);
// Card contextSystem.out.println("Card: " + pricing.getCard().getName());
System.out.println("Set: " + pricing.getCard().getSet().getName()
+ " (" + pricing.getCard().getSet().getYear() + ")");
// Raw (ungraded) salesSystem.out.println("Ungraded sales: " + pricing.getRaw().getCount());
pricing.getRaw().getRecords().forEach(sale ->
System.out.println(" $" + sale.getPrice() + " - " + sale.getDate() + " (" + sale.getSource() + ")"));
// Graded sales (grouped by company -> grade)pricing.getGraded().forEach(company -> {
System.out.println(company.getCompanyName() + ":");
company.getGrades().forEach(grade ->
System.out.println(" Grade " + grade.getGradeValue() + ": " + grade.getCount() + " sales"));
});
// MetadataSystem.out.println("Total records: " + pricing.getMeta().getTotalRecords());
System.out.println("Last sale: " + pricing.getMeta().getLastSaleDate());Bulk pricing for multiple cards (up to 100):
importai.cardsight.generated.model.BulkPricingRequestInput;
importjava.util.List;
importjava.util.UUID;
BulkPricingRequestInputrequest = newBulkPricingRequestInput();
request.setCardIds(List.of(UUID.fromString("card_uuid_1"), UUID.fromString("card_uuid_2")));
request.setPeriod("90d");
varbulk = client.pricing().getBulkPricing(request);
System.out.println("Successful: " + bulk.getMeta().getSuccessful());Search completed sales by listing title when you don't have a card ID. Returns a flat, relevance-ranked list that spans multiple cards:
// q (3-300 chars), period, listingType, limitvarresults = client.pricing().searchPricingByTitle("Ken Griffey Jr 1989 Upper Deck", "90d", "both", 25);
System.out.println("Found " + results.getMeta().getTotalRecords() + " sales");
results.getResults().forEach(sale ->
System.out.println("$" + sale.getPrice() + " - " + sale.getTitle() + " (" + sale.getSource() + ")"));Get currently active marketplace listings for a card. Same shape as pricing, but with active listings instead of completed sales:
importai.cardsight.generated.model.MarketplaceResponse;
// cardId, parallelId, gradeId, listingType, limitMarketplaceResponselistings = client.marketplace()
.getCardMarketplace("card_uuid", null, null, "both", 25);
System.out.println("Ungraded listings: " + listings.getRaw().getCount());
listings.getRaw().getRecords().forEach(listing -> {
System.out.println(" " + listing.getTitle() + " - $" + listing.getPrice() + " (" + listing.getSource() + ")");
if (listing.getUrl() != null) System.out.println(" " + listing.getUrl());
});// q (3-300 chars), listingType, limitvarresults = client.marketplace().searchMarketplaceByTitle("Ken Griffey Jr 1989 Upper Deck", "both", 25);
System.out.println("Found " + results.getMeta().getTotalRecords() + " active listings");Retrieve cards, sets, releases, and other catalog data:
// Search for cards:// take, skip, name, number, releaseId, releaseName, year, minYear, maxYear,// cardSetId, cardSetName, manufacturer, attributeId, attributeShortName, field, sort, ordervarcards = client.catalog().getCards(
20, 0, "Charizard", null, null, null, "2024",
null, null, null, null, null, null, null, null, "name", "asc");
cards.getCards().forEach(c -> System.out.println(c.getName() + " #" + c.getNumber()));
// Get a specific card by IDvarcard = client.catalog().getCard("card_uuid");
// Sets: take, skip, releaseId, name, year, minYear, maxYear, manufacturer, isIdentifiable, sort, ordervarsets = client.catalog().getSets(20, 0, null, null, "2023", null, null, "Topps", null, "year", "desc");
// Cards in a specific set: id, take, skip, name, number, sort, ordervarsetCards = client.catalog().getSetCards("set_uuid", 50, 0, null, null, "number", "asc");
// Releases (product lines like "Chrome", "Series 1")varreleases = client.catalog().getReleases(20, 0, null, null, null, "2020", "2024", "Chrome", null, "year", "desc");
// Manufacturers and segmentsvarmanufacturers = client.catalog().getManufacturers(50, 0, null, "name", "asc");
varsegments = client.catalog().getSegments(50, 0, null, null, "name", "asc");
// Parallelsvarparallels = client.catalog().getParallels(20, 0, null, null, null, null, null, null, "name", "asc");
varparallel = client.catalog().getParallel("parallel_uuid");
// Catalog statistics (each stat group exposes getTotal(), plus breakdowns)varstats = client.catalog().getStatistics();
System.out.println("Total cards: " + stats.getCards().getTotal());
System.out.println("Total sets: " + stats.getSets().getTotal());Browse upcoming and recent card product releases, sorted by release date (newest first):
// take, skip, segment, manufacturer, year (segment/manufacturer accept UUIDs or names)varcalendar = client.releaseCalendar().getReleaseCalendar(20, 0, null, "Panini", "2026");
calendar.getReleaseCalendar().forEach(entry -> {
StringpreOrder = entry.getPreOrderDate() != null ? entry.getPreOrderDate() : "N/A";
System.out.println(entry.getName() + " — releases " + entry.getReleaseDate()
+ " (pre-order: " + preOrder + ")");
});
System.out.println("Total upcoming: " + calendar.getTotalCount());The random endpoints enable pack-opening simulations and discovery features by returning random results instead of sorted, paginated ones:
// Pack opening — 10 random cards from a set, with parallel conversion odds.// Params: name, number, releaseId, releaseName, year, minYear, maxYear, cardSetId,// cardSetName, manufacturer, attributeId, attributeShortName, field, sort,// order, count, includeParallelsvarpack = client.catalog().getRandomCards(
null, null, null, null, null, null, null, "set_uuid",
null, null, null, null, null, null, null, 10, true);
// Discovery — 5 random releases from 2023varrandomReleases = client.catalog().getRandomReleases(
null, null, "2023", null, null, null, null, null, null, 5);
// Random sets from a specific releasevarrandomSets = client.catalog().getRandomSets(
"release_uuid", null, null, null, null, null, null, null, null, 6);Get graded population counts for a card, set, or release:
importai.cardsight.generated.model.CardPopulationResponse;
// cardId, gradingCompanyId (gradingCompanyId optional — pass null for all companies)CardPopulationResponsepop = client.population().getCardPopulation("card_uuid", null);
System.out.println(pop.getCardName() + " — total graded population: " + pop.getTotalPopulation());
// Also available:client.population().getSetPopulation("set_uuid", null);
client.population().getReleasePopulation("release_uuid", null);Manage personal card collections with analytics:
importai.cardsight.generated.model.CreateCollectionInput;
importjava.util.UUID;
// Create a collection (collectorId links it to a collector profile)CreateCollectionInputinput = newCreateCollectionInput();
input.setName("My Vintage Cards");
input.setDescription("Pre-1980 baseball cards");
input.setCollectorId(UUID.fromString("collector_uuid"));
varcollection = client.collections().createCollection(input);
UUIDcollectionId = UUID.fromString(collection.getId());
// Collection analyticsvaranalytics = client.collections().getCollectionAnalytics(collectionId);
System.out.println("Total cards: " + analytics.getOverview().getTotalCards());
System.out.println("Unique cards: " + analytics.getOverview().getUniqueCards());
System.out.println("Total invested: " + analytics.getFinancials().getTotalInvested());
// Breakdown by category: groupBy ("year" | "manufacturer" | "set" | "grade"), collectionId, take, skip, sortBy, order, minCountvarbreakdown = client.collections().getCollectionBreakdown("year", collectionId, 20, 0, null, "desc", null);
// List collections for a collector: take, skip, collectorId, name, sort, ordervarcollections = client.collections().getCollections(10, 0, UUID.fromString("collector_uuid"), null, "name", "asc");Adding and updating cards is done with addCollectionCards(collectionId, CreateCollectionCardInput) and updateCollectionCard(collectionId, cardId, UpdateCollectionCardInput) (which supports setBuyPrice, setBuyDate, setGradeId, setSellPrice, setSoldDate, and more).
Organize collection cards into binders (subsets):
importai.cardsight.generated.model.CreateBinderInput;
importjava.util.UUID;
UUIDcollectionId = UUID.fromString("collection_uuid");
CreateBinderInputbinderInput = newCreateBinderInput();
binderInput.setName("Hall of Famers");
binderInput.setDescription("Cards of HOF players");
varbinder = client.collections().createBinder(collectionId, binderInput);
// List cards in a binder: collectionId, binderId, take, skipvarbinderCards = client.collections().getBinderCards(collectionId, binder.getId(), 20, 0);Track cards you want to acquire:
importai.cardsight.generated.model.CreateListInput;
CreateListInputlistInput = newCreateListInput();
listInput.setName("Rookies to Find");
listInput.setDescription("2024 rookie cards I need");
listInput.setCollectorId("collector_uuid");
varlist = client.lists().createList(listInput);
// Get cards in a list: listId, take, skipvarlistCards = client.lists().getListCards(list.getId(), 20, 0);
// Remove a card once acquiredclient.lists().removeCardFromList(list.getId(), "card_uuid");Access grading company data and grade values:
importjava.util.UUID;
// All grading companies (PSA, BGS, SGC, etc.)varcompanies = client.grading().getGradingCompanies();
companies.getCompanies().forEach(c -> System.out.println(c.getName()));
// Grading types for a company, then grades for a typevartypes = client.grading().getGradingTypes(UUID.fromString("company_uuid"));
vargrades = client.grading().getGrades(UUID.fromString("company_uuid"), UUID.fromString("type_uuid"));Use natural language to query the catalog:
importai.cardsight.generated.model.AIQueryRequestInput;
AIQueryRequestInputquery = newAIQueryRequestInput();
query.setQuery("Show me Mike Trout rookie cards worth over $100");
varresponse = client.ai().processAIQuery(query);
System.out.println(response.getAnswer());Provide search suggestions for users. Autocomplete methods return a List<String> of suggestions:
// q, cardSetId, releaseId, segmentId, manufacturerId, yearvarcards = client.autocomplete().autocompleteCards("aaron", null, null, null, null, null);
cards.getSuggestions().forEach(System.out::println); // "Aaron Judge", "Hank Aaron", ...// Other entitiesvarsets = client.autocomplete().autocompleteSets("chrome", null, null, null, null);
varmanufacturers = client.autocomplete().autocompleteManufacturers("top", null);
varyears = client.autocomplete().autocompleteYears("202", null, null);Card images are returned as a java.io.File:
importjava.io.File;
importjava.util.UUID;
// Get a card image: id, format ("json" for base64 JSON), _default ("true" for placeholder fallback)Fileimage = client.images().getCardImage(UUID.fromString("card_uuid"), null, null);
// Collection card images and thumbnailsFilecollectionImage = client.collectionImages()
.getCollectionCardImage(UUID.fromString("collection_uuid"), UUID.fromString("card_uuid"));
Filethumbnail = client.collectionImages()
.getCollectionCardImageThumbnail(UUID.fromString("collection_uuid"), UUID.fromString("card_uuid"));Submit feedback to improve the platform:
importai.cardsight.generated.model.FeedbackInputInput;
importjava.util.UUID;
FeedbackInputInputfeedback = newFeedbackInputInput();
// ... populate feedback fields ...// Report an identification issue (id = identification request ID)client.feedback().submitIdentifyFeedback(UUID.fromString("identification_request_id"), feedback);
// General feedback, or feedback on a specific catalog entityclient.feedback().submitGeneralFeedback(feedback);
client.feedback().submitCardFeedback(UUID.fromString("card_uuid"), feedback);Every request parameter and response is a strongly typed, auto-generated Java class in the ai.cardsight.generated.model package, so your IDE gives you full autocomplete and the compiler catches mistakes:
importai.cardsight.generated.model.IdentifyCardResponse;
importai.cardsight.generated.model.IdentificationData;
importai.cardsight.generated.model.CardDetails;
importai.cardsight.generated.model.CatalogSearchResponse;
importai.cardsight.generated.model.PricingResponse;
IdentifyCardResponseresult = client.cardIdentification().identifyCard(newFile("card.jpg"));
// The compiler knows the exact shape of every response:for (IdentificationDatadetection : result.getDetections()) {
CardDetailscard = detection.getCard();
// ...
}Enumerated values are generated as Java enums (for example IdentificationData.ConfidenceEnum.HIGH, MEDIUM, LOW).
Every API method throws ai.cardsight.generated.client.ApiException (a checked exception) on a non-2xx response. Inspect getCode() for the HTTP status and getResponseBody() for the raw error payload:
importai.cardsight.generated.client.ApiException;
try {
varresult = client.cardIdentification().identifyCard(newFile("card.jpg"));
} catch (ApiExceptione) {
System.err.println("API Error " + e.getCode() + ": " + e.getMessage());
System.err.println("Response body: " + e.getResponseBody());
switch (e.getCode()) {
case401 -> System.err.println("Authentication failed - check your API key");
case429 -> System.err.println("Rate limited - wait before retrying");
case500, 502, 503, 504 -> System.err.println("Server error - retry later");
default -> { /* handle other status codes */ }
}
}importai.cardsight.CardSightAI;
importjava.time.Duration;
// Basic — API key passed directlyCardSightAIclient = newCardSightAI("your_api_key");
// From the CARDSIGHTAI_API_KEY environment variableCardSightAIfromEnv = newCardSightAI();
// Advanced — builder with custom base URL, timeout, and headersCardSightAIcustom = CardSightAI.builder()
.apiKey("your_api_key")
.baseUrl("https://api.cardsight.ai")
.timeout(Duration.ofSeconds(30))
.addHeader("X-Custom-Header", "value")
.build();The client's primary constructor is annotated with Jakarta @Inject, so it works with Spring, CDI, and Guice. Provide a CardSightConfig and inject CardSightAI:
importai.cardsight.CardSightAI;
importai.cardsight.config.CardSightConfig;
importorg.springframework.beans.factory.annotation.Value;
importorg.springframework.context.annotation.Bean;
importorg.springframework.context.annotation.Configuration;
@ConfigurationclassCardSightConfiguration {
@BeanCardSightConfigcardSightConfig(@Value("${cardsight.api-key}") StringapiKey) {
returnCardSightConfig.builder().apiKey(apiKey).build();
}
@BeanCardSightAIcardSightAI(CardSightConfigconfig) {
returnnewCardSightAI(config);
}
}CARDSIGHTAI_API_KEY=your_api_key_here # API key for authenticationThe SDK provides full coverage of the CardSight AI REST API, grouped into typed accessors on the client:
| Category | Methods | Accessor |
|---|---|---|
| Health | 2 | health().getHealth(), getHealthAuthenticated() |
| Identification | 4 | cardIdentification().identifyCard(), identifyCardBySegment(), listIdentifiableSets(), checkSetIdentifiable() |
| Detection | 1 | detection().detectCard() |
| Catalog | 21 | catalog().searchCatalog(), getCards(), getSets(), getReleases(), getFields(), getParallels(), getRandomCards(), getStatistics(), … |
| Release Calendar | 1 | releaseCalendar().getReleaseCalendar() |
| Collections | 23 | collections().* (collections, cards, binders, analytics, breakdown, set progress) |
| Collectors | 5 | collectors().* |
| Lists | 8 | lists().* |
| Pricing | 3 | pricing().getCardPricing(), getBulkPricing(), searchPricingByTitle() |
| Marketplace | 2 | marketplace().getCardMarketplace(), searchMarketplaceByTitle() |
| Population | 3 | population().getCardPopulation(), getSetPopulation(), getReleasePopulation() |
| Grades | 3 | grading().getGradingCompanies(), getGradingTypes(), getGrades() |
| Autocomplete | 6 | autocomplete().* |
| AI | 1 | ai().processAIQuery() |
| Images | 4 | images().getCardImage(), collectionImages().* |
| Feedback | 8 | feedback().* |
| Subscription | 1 | subscription().getSubscription() |
- Java 21 or higher
- Maven 3.6 or higher
- Node.js (used to preprocess the OpenAPI spec during the build)
# Clone the repository
git clone https://github.com/CardSightAI/cardsightai-sdk-java.git
cd cardsightai-sdk-java
# Build and install to your local Maven repository
mvn clean installThe build automatically preprocesses the bundled OpenAPI specification, generates the client, and compiles everything.
The SDK is generated from the CardSight AI OpenAPI specification. To pull the latest spec and regenerate:
mvn clean compile -Pdownload-specmvn testContributions are welcome! Please open an issue or pull request on GitHub.
This SDK is licensed under the MIT License. See the LICENSE file for details.
- Email: support@cardsight.ai
- Website: cardsight.ai
- API Documentation: api.cardsight.ai/documentation
- Issues: GitHub Issues
Built with ❤️ by CardSight AI