Understanding Responses

Learn about the SDK's response structure and data transformation features.

Response Structure

All successful method calls from the client return a consistent JustTCGApiResponse object. This provides a predictable structure for handling API responses.

interface JustTCGApiResponse<T> {
  /** The main data payload from the API */
  data: T;
  
  /** Pagination metadata (only on paginated endpoints) */
  pagination?: {
    total: number;
    limit: number;
    offset: number;
    hasMore: boolean;
  };
  
  /** API usage metadata (included in every response) */
  usage: {
    apiRequestLimit: number;
    apiDailyLimit: number;
    apiRateLimit: number;
    apiRequestsUsed: number;
    apiDailyRequestsUsed: number;
    apiRequestsRemaining: number;
    apiDailyRequestsRemaining: number;
    apiPlan: string;
  };
  
  /** Error message (if API returns an error) */
  error?: string;
  code?: string;
}
Type Safety: The T generic parameter ensures that response.data is fully typed based on the method you're calling.

Card Object Structure

The SDK provides clean, typed interfaces for all data structures. Here's the Card object structure:

interface Card {
    /** The unique identifier for the card */
    id: string;
    
    /** The name of the card */
    name: string;
    
    /** The game this card belongs to */
    game: string;
    
    /** The set ID this card belongs to */
    set: string;

    /** The set name this card belongs to */
    set_name: string;
    
    /** The card number within the set */
    number: string | null;
    
    /** The rarity of the card */
    rarity: string | null;
    
    /** The TCGPlayer ID for the card */
    tcgplayerId: string | null;
    
    /** Additional details about the card */
    details?: string | null;
    
    /** The different variants of the card */
    variants: Variant[];
  }

Variant Object Structure

Each card contains an array of variants with detailed pricing information:

interface Variant {
  /** The unique identifier for this variant. */
  id: string;

  /** The condition of the card variant (e.g., Near Mint). */
  condition: string;

  /** The printing type of the card variant (e.g., Foil, 1st Edition). */
  printing: string;

  /** The language of the card variant, if applicable. */
  language: string | null;

  /** The current price of the card variant in dollars. */
  price: number;

  /** The last time the price was updated, as an epoch timestamp in seconds. */
  lastUpdated: number; // Epoch seconds

  /** The percentage change in price over the last 24 hours. */
  priceChange24hr?: number | null; // Percentage

  // --- 7d stats ---
  /** The percentage change in price over the last 7 days. */
  priceChange7d?: number | null; // Percentage
  /** The average price over the last 7 days. */
  avgPrice?: number | null; // Dollars
  /** The price history entries over the last 7 days. */
  priceHistory?: PriceHistoryEntry[] | null;
  minPrice7d?: number | null; // Dollars
  maxPrice7d?: number | null; // Dollars
  stddevPopPrice7d?: number | null;
  covPrice7d?: number | null;
  iqrPrice7d?: number | null;
  trendSlope7d?: number | null;
  priceChangesCount7d?: number | null;

  // --- 30d stats ---
  priceChange30d?: number | null; // Percentage
  avgPrice30d?: number | null; // Dollars
  minPrice30d?: number | null; // Dollars
  maxPrice30d?: number | null; // Dollars
  priceHistory30d?: PriceHistoryEntry[] | null;
  stddevPopPrice30d?: number | null;
  covPrice30d?: number | null;
  iqrPrice30d?: number | null;
  trendSlope30d?: number | null;
  priceChangesCount30d?: number | null;
  priceRelativeTo30dRange?: number | null;

  // --- 90d stats ---
  priceChange90d?: number | null; // Percentage
  avgPrice90d?: number | null; // Dollars
  minPrice90d?: number | null; // Dollars
  maxPrice90d?: number | null; // Dollars
  stddevPopPrice90d?: number | null;
  covPrice90d?: number | null;
  iqrPrice90d?: number | null;
  trendSlope90d?: number | null;
  priceChangesCount90d?: number | null;
  priceRelativeTo90dRange?: number | null;

  // --- 1y stats ---
  minPrice1y?: number | null;
  maxPrice1y?: number | null;

  // --- All-time stats ---
  minPriceAllTime?: number | null;
  minPriceAllTimeDate?: string | null;
  maxPriceAllTime?: number | null;
  maxPriceAllTimeDate?: string | null;
}

Price History Structure

Price history is provided as an array of timestamped price points:

interface PriceHistoryEntry {
  /** Epoch timestamp in seconds */
  t: number;
  
  /** Price in dollars */
  p: number;
}

Example Usage

const response = await client.v1.cards.get({ cardId: 'some-card-id' });
const card = response.data[0];
const variant = card.variants[0];

if (variant.priceHistory) {
  // Convert timestamps to dates and plot price history
  const pricePoints = variant.priceHistory.map(entry => ({
    date: new Date(entry.t * 1000),
    price: entry.p
  }));

  console.log('Price history:', pricePoints);
}

Pagination

Paginated endpoints include pagination metadata in the response:

interface PaginationInfo {
  /** Total number of results available */
  total: number;
  
  /** Number of results per page */
  limit: number;
  
  /** Number of results skipped */
  offset: number;
  
  /** Whether there are more results available */
  hasMore: boolean;
}

Example Pagination Usage

const response = await client.v1.cards.get({
  game: 'Pokemon',
  limit: 20,
  offset: 0
});

console.log('Results:', response.data.length);
console.log('Total available:', response.pagination?.total);
console.log('Has more:', response.pagination?.hasMore);

// Load next page
if (response.pagination?.hasMore) {
  const nextPage = await client.v1.cards.get({
    game: 'Pokemon',
    limit: 20,
    offset: 20
  });
}

Usage Metadata

Every response includes usage metadata to help you monitor your API consumption:

interface UsageInfo {
  /** Your total request limit */
  apiRequestLimit: number;
  
  /** Your daily request limit */
  apiDailyLimit: number;
  
  /** Your rate limit (requests per minute) */
  apiRateLimit: number;
  
  /** Requests used in this call */
  apiRequestsUsed: number;
  
  /** Daily requests used */
  apiDailyRequestsUsed: number;
  
  /** Requests remaining in this call */
  apiRequestsRemaining: number;
  
  /** Daily requests remaining */
  apiDailyRequestsRemaining: number;
  
  /** Your current plan */
  apiPlan: string;
}

Example Usage Monitoring

const response = await client.v1.games.list();

console.log('API Plan:', response.usage.apiPlan);
console.log('Daily requests used:', response.usage.apiDailyRequestsUsed);
console.log('Daily requests remaining:', response.usage.apiDailyRequestsRemaining);

// Check if approaching limits
const usagePercentage = (response.usage.apiDailyRequestsUsed / response.usage.apiDailyLimit) * 100;
if (usagePercentage > 80) {
  console.warn('Approaching daily limit!');
}

Next Steps