---
title: "Get Fair Market Value (FMV) by GemRate ID"
method: POST
path: "/v1/cards/fmv-by-gemrate-id"
tags: ["Pricing & Valuations"]
---

# Get Fair Market Value (FMV) by GemRate ID

`POST /v1/cards/fmv-by-gemrate-id`

## Request

- Base URL: `https://api.cardhedger.com`
- URL: `https://api.cardhedger.com/v1/cards/fmv-by-gemrate-id`
- Auth: API key in header `X-API-Key`

Get the Fair Market Value (FMV) for a card by GemRate ID.

The GemRate-ID analog of `/v1/cards/fmv-by-cert`. A GemRate ID
identifies a card rather than a specific graded copy, so the grade
must be supplied by the caller (same format as `/v1/cards/card-fmv`:
'PSA 10', 'BGS 9.5', 'Raw', '<Provider> Auth').

## How it works

1. Resolves the GemRate ID to a CardHedge card: direct lookup, then the
   persistent cert-resolution cache, then the GemRate population API
   (description + sibling IDs) with an AI `card-match` fallback.
2. Requests the FMV for the resolved card at the requested grade.

## Card resolution (`card_source` / `match_confidence`)

- `card_source: "gemrate_id"` — direct GemRate ID → CardHedge lookup
  succeeded. `match_confidence` is null.
- `card_source: "card_match"` — the card was matched from the GemRate
  description via the AI fallback. `match_confidence` (0-1) is the
  matcher's score; **treat an FMV derived from a low-confidence match
  with care**. Cards resolved this way have null `category_group` and
  `set_type`.

## FMV (`fmv`)

The `fmv` object is identical to the `/v1/cards/card-fmv` response — see
that endpoint for the full method cascade (`direct`, `card_interpolation`,
`cross_provider`, `anchor_multiplier`, `segment_fallback`, `no_data`),
`_indexed` variants, confidence grading, and movement-index metadata.

## Status codes and nulls

- `200` with `card: null` and `fmv: null` — GemRate knows the ID but no
  CardHedge card matched.
- `404` — the ID is unknown to both CardHedge and GemRate.
- `502` — an upstream API failed.
- A found card with insufficient sale data returns a populated `fmv`
  with `method: "no_data"` and `price: null`.

**Example curl:**
```bash
curl -X POST -H "X-API-Key: your-api-key-here" \
     -H "Content-Type: application/json" \
     -d '{
       "gemrate_id": "25783324b9710f1366ca4d54f3dd4689c02b6885",
       "grade": "PSA 10"
     }' \
     "https://api.cardhedger.com/v1/cards/fmv-by-gemrate-id"
```

## Request body

- FMVByGemrateIdRequest: Request parameters for the FMV-by-gemrate-id endpoint.
  - `gemrate_id` string, required: GemRate card identifier (grader-specific or universal)
  - `grade` string, required: Card grade label. Supported formats: '<Provider> <Grade>' (e.g., 'PSA 9', 'PSA 10', 'BGS 9.5', 'SGC 9', 'CGC 10'), 'Raw' for ungraded, or '<Provider> Auth' for authenticated-only.

## Response `200`

Successful Response

- FMVByGemrateIdResponse: Response model for the FMV-by-gemrate-id endpoint.
  - `gemrate_info` GemRateIdInfo, required: Identification context for a GemRate-ID lookup. The analog of `GemRateCertInfo` for the gemrate-id endpoints. `universal_gemrate_id` and `description` come from the GemRate hybrid-population-data fallback, so they are populated only when that fallback actually ran (a direct CardHedge hit never calls GemRate). Population statistics are deliberately excluded, consistent with the cert endpoints.
    - `gemrate_id` string, required: GemRate ID exactly as provided by the caller
    - `universal_gemrate_id` string, nullable: Universal GemRate ID from the GemRate population lookup. Null when the card was resolved without calling GemRate (direct CardHedge hit or cache hit).
    - `description` string, nullable: Card description from the GemRate population lookup. Null when the card was resolved without calling GemRate.
  - `card` CardDetails: Detailed card information and metadata.
    - `card_id` string, required: Unique card identifier
    - `description` string, nullable: Full card description
    - `player` string, nullable: Player or character name
    - `set` string, nullable: Card set name
    - `number` string, nullable: Card number in set
    - `variant` string, nullable: Card variant (e.g., Base, Refractor, Prizm)
    - `image` string, nullable: Card image URL
    - `category` string, nullable: Card category (e.g., Baseball, Basketball, Pokemon)
    - `category_group` string, nullable: Category group, derived from the catalog category for indexed cards
    - `set_type` string, nullable: Set type, derived from the catalog set name for indexed cards
  - `fmv` CardFMVResponse: Response model for the card FMV endpoint. Mirrors the upstream FMV service response. Any additional fields returned by the upstream are preserved via ``extra='allow'`` so consumers receive the full payload even if the upstream adds new fields.
    - `price` number, nullable: Fair market value in USD (null when no data available)
    - `price_low` number, nullable: Lower bound of the FMV range (null when no data available)
    - `price_high` number, nullable: Upper bound of the FMV range (null when no data available)
    - `confidence` number, nullable: Confidence score (0-1) for the FMV calculation
    - `method` string, nullable: FMV calculation method. One of 11 values from the cascade: **Base methods (in priority order):** - `direct` — Exact card+grade lookup. Latest_price is replaced with a Winsorized-median FMV over a 7/15/30/90-day window when enough daily prints exist; otherwise latest_price is used as-is. - `card_interpolation` — No direct price; isotonic regression in log-space across the card's OTHER same-provider grades, then interpolating/extrapolating to the target grade. - `cross_provider` — No same-provider data; translates from another grader (e.g., BGS 9 → PSA 9) using a learned price ratio. - `anchor_multiplier` — Uses one same-provider grade as an anchor and applies a within-provider grade multiplier. Variants include same-provider, chained (e.g., BGS 8.5 → BGS 9 → PSA 9), and raw (Raw card price → graded). See `anchor_from_raw` / `anchor_chained_from_provider`. - `segment_fallback` — Last resort: uses the set/year × category baseline price and applies a grade multiplier. - `no_data` — No sale data could produce a value; `price` is null. **`_indexed` variants** (`direct_indexed`, `card_interpolation_indexed`, `cross_provider_indexed`, `anchor_multiplier_indexed`, `segment_fallback_indexed`) — the base method produced a stale price, so a movement index was overlaid to bring it to today. See `index_level`, `index_pct_change`, and `raw_price` for the adjustment details.
    - `freshness_days` integer, nullable: Age of the underlying sale data in days (0 = today). On `_indexed` methods this reflects the index's `as_of_date`, not the base price's age. Null on `segment_fallback` and `no_data`.
    - `support_grades` integer, nullable: Number of grade data points contributing to the estimate. 1 for `direct`; 2+ for `card_interpolation` (other grades of this card); 1 for `anchor_multiplier`; 0 for `segment_fallback` / `no_data`.
    - `grade_label` string, nullable: Normalized grade label the FMV was computed for (e.g., 'PSA 9', 'BGS 9.5', 'Raw').
    - `provider` string, nullable: Grading provider (e.g., 'PSA', 'BGS', 'SGC', 'CGC', 'Raw').
    - `grade_value` number, nullable: Numeric grade value (e.g., 9.0, 9.5, 10.0). 0 for Raw; negative values denote authenticated-only grades (e.g., 'PSA Auth').
    - `as_of_date` string, nullable: ISO 8601 date the applied movement index was last computed. Set only on `_indexed` methods; null otherwise.
    - `index_level` string, nullable: Cascade level used for movement adjustment. One of: - `card_grade` — most specific: this card at this grade - `card` — blended across all grades of this card - `player` — player-level index (all cards of this player) - `segment` — (year × category) segment-level index - `none` — stale price, but no index met the minimum sample threshold (an `un_indexed_penalty` is applied to confidence) - `null` — fresh estimate, no movement adjustment needed
    - `index_pct_change` number, nullable: Cumulative percent change applied by the movement index over the FMV's lookback window (decimal, e.g., 0.157 = +15.7%). Set only on `_indexed` methods.
    - `raw_price` number, nullable: Pre-adjustment price in USD. For `direct`: the chosen FMV value (or the original `latest_price` when no FMV qualified). For other cascade methods: the original method result before any movement adjustment. Compare `price` vs `raw_price` to see what the movement index changed.
    - `index_truncated` boolean, nullable: True if the FMV's lookback window was capped at the maximum (730 days) because the underlying price was extremely stale. Treat truncated movement adjustments as lower-confidence.
    - `fmv_window_days` integer, nullable: FMV smoothing window used for the base price. One of 7, 15, 30, or 90 — the upstream picks the shortest window with enough samples. Null when no FMV smoothing was applied (the lookup fell back to `card_grade_prices.latest_price`, or the method is not `direct`).
    - `fmv_sample_count` integer, nullable: Number of distinct daily prints that fed the chosen FMV's Winsorized median. Higher = more reliable. Null when no FMV was applied.
    - `base_sample_count` integer, nullable: Number of sales behind the base latest_price (90-day sale count on the source grade row). Only set on `direct` lookups that did NOT substitute a Winsorized-median FMV — where `fmv_sample_count` is present it describes the FMV instead. Use to tell a well-backed latest_price from a single-sale print; null means the source reported no sale count.
    - `index_sample_count` integer, nullable: Number of observations at the chosen movement-index window. Useful for filtering low-signal adjustments — e.g., ignore `index_pct_change` when `index_sample_count < 10`.
    - `confidence_grade` string, nullable: Bucketed confidence grade — a quick proxy for the numeric `confidence`: - `A` — confidence ≥ 0.42 (~86% of prices within 2× of the actual sale). Trust for valuations. - `B` — confidence ≥ 0.25 (~74% within 2×). Usable; consider showing `raw_price` too. - `C` — confidence ≥ 0.10 (~63% within 2×). Borderline; consider falling back to `latest_price` for sensitive decisions. - `D` — confidence < 0.10 (~49% within 2×). Likely noisy; show with disclaimer. Cutoffs are calibrated to measured accuracy on held-out sales and may be re-tuned as the model improves — rely on the letter grade rather than hard-coding numeric thresholds. Null on `no_data`. The numeric `confidence` already folds in cascade method, FMV signal strength, and movement-index quality, so this single grade reflects total trust in the returned price.
    - `price_explanation` string, nullable: Human-readable description of how the FMV was derived — e.g., 'Used 7d FMV ($416.25, Winsorized median of 3 daily prints) in place of latest_price $416.25. Fresh (1d) — no movement adjustment applied.' Useful for debug UIs and audit trails; not intended for programmatic parsing (wording may change).
    - `cross_grade_fmv_count` integer, nullable: For cross-grade methods (`card_interpolation`, `cross_provider`, `anchor_multiplier`): count of source grades whose `latest_price` was replaced with a Winsorized-median FMV before the cascade ran. Higher = more smoothing applied. Null when the method wasn't used; 0 when used but no FMV qualified for any source.
  - `card_source` string, nullable: How the card was resolved: 'gemrate_id' for a direct GemRate ID -> CardHedge lookup, or 'card_match' when that lookup found nothing and the card was matched from the GemRate description via the AI card-match fallback. Null when no card was resolved. Cards resolved via 'card_match' have null 'category_group' and 'set_type' -- the matcher does not return those two fields.
  - `match_confidence` number, nullable: AI match confidence (0-1) when 'card_source' is 'card_match'; null otherwise. Treat an FMV derived from a low-confidence match with care.

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/cardhedger/apis/card-hedge-api.md) - [All operations](https://skmtc.dev/cardhedger/apis/card-hedge-api/llms.txt) - [OpenAPI document](https://skmtc.dev/cardhedger/apis/card-hedge-api/revisions/6de42f192a4d?raw)
