---
title: "Compare evidence-backed access catalogs for two confirmed profiles"
method: POST
path: "/v1/access-catalog/compare"
tags: ["Primary - Decisions"]
---

# Compare evidence-backed access catalogs for two confirmed profiles

`POST /v1/access-catalog/compare`

## Request

- Base URL: `https://api.rateapi.dev`
- URL: `https://api.rateapi.dev/v1/access-catalog/compare`
- Auth: API key in header `X-API-Key`

Evaluates baseline and candidate profiles against one immutable exhaustive eligibility graph snapshot and identical explicit product selectors. Rate rows retain their independent evidence and as_of. Deltas do not claim savings, underwriting, approval, or denial. Authentication required.

## Request body

- object
  - `baseline_person` Person, required (unresolved $ref)
  - `candidate_person` Person, required (unresolved $ref)
  - `products` Products, required (unresolved $ref)
  - `limit_per_product` LimitPerProduct (unresolved $ref)
  - `total_limit` TotalLimit (unresolved $ref)

## Response `200`

Full baseline and candidate catalogs with structured per-product and portfolio deltas.

- AccessCatalogCompareResponse: Full baseline and candidate access catalogs plus evidence-linked cross-product changes under one eligibility graph snapshot.
  - `comparison_version` 'access_catalog_compare_v1', required: Stable comparison response contract version.
  - `baseline` AccessCatalogResponse, required: One-snapshot, multi-product personal access catalog with explicit semantic layers and bounded details.
    - `catalog_version` 'access_catalog_v1', required: Stable response-contract version.
    - `products` object[], required: One result in request order for every explicit product selector.
      - `request` Product, required (unresolved $ref)
      - `ranking_basis` string, required: Published-price ordering used within this selector.
      - `ranking` object, required: Explicit declaration of the decision layers this ranking does not perform.
        - `personalized_underwriting` false, required: Always false; catalog ranking is not underwriting.
        - `approval_evaluated` false, required: Always false; RateAPI does not make approval decisions.
      - `counts` Counts, required (unresolved $ref)
      - `reachable_now` AccessCatalogRow[], required: Rows with proven present membership access, satisfied published constraints, and evidenced pricing.
        - `credit_union_id` string, required: Stable credit-union identifier.
        - `institution` object, required: Institution name, state, and published URL where available.
        - `membership` object, required: Positive-evidence-only membership verdict and active-publication proof.
        - `product_availability` object, required: Whether matching fresh evidenced published pricing was found; unknown never means unavailable.
        - `product_suitability` object: Evaluation of only the explicit published constraints and supplied scenario facts.
        - `published_price` object: Fresh, rankable published price with explicitly published APY for deposits and published APR or clearly labeled nominal rate for lending, plus source evidence and per-row as_of. APR and nominal rate are never treated as interchangeable.
        - `underwriting` object, required: Explicit statement that creditworthiness and underwriting were not evaluated.
          - `status` 'not_evaluated', required: Catalog underwriting status; always not_evaluated.
          - `reason` string, required: Why no underwriting conclusion may be drawn.
        - `approval` object, required: Explicit statement that RateAPI did not evaluate or grant approval.
          - `status` 'not_evaluated_by_rateapi', required: Approval status; always not_evaluated_by_rateapi.
          - `reason` string, required: Why only the institution can approve and confirm final terms.
      - `reachable_after_action` AccessCatalogRow[], required: Rows requiring a source-proven membership action before access.
        - `credit_union_id` string, required: Stable credit-union identifier.
        - `institution` object, required: Institution name, state, and published URL where available.
        - `membership` object, required: Positive-evidence-only membership verdict and active-publication proof.
        - `product_availability` object, required: Whether matching fresh evidenced published pricing was found; unknown never means unavailable.
        - `product_suitability` object: Evaluation of only the explicit published constraints and supplied scenario facts.
        - `published_price` object: Fresh, rankable published price with explicitly published APY for deposits and published APR or clearly labeled nominal rate for lending, plus source evidence and per-row as_of. APR and nominal rate are never treated as interchangeable.
        - `underwriting` object, required: Explicit statement that creditworthiness and underwriting were not evaluated.
          - `status` 'not_evaluated', required: Catalog underwriting status; always not_evaluated.
          - `reason` string, required: Why no underwriting conclusion may be drawn.
        - `approval` object, required: Explicit statement that RateAPI did not evaluate or grant approval.
          - `status` 'not_evaluated_by_rateapi', required: Approval status; always not_evaluated_by_rateapi.
          - `reason` string, required: Why only the institution can approve and confirm final terms.
      - `unresolved` AccessCatalogRow[], required: Rows that cannot be promoted because membership proof or product suitability remains unresolved.
        - `credit_union_id` string, required: Stable credit-union identifier.
        - `institution` object, required: Institution name, state, and published URL where available.
        - `membership` object, required: Positive-evidence-only membership verdict and active-publication proof.
        - `product_availability` object, required: Whether matching fresh evidenced published pricing was found; unknown never means unavailable.
        - `product_suitability` object: Evaluation of only the explicit published constraints and supplied scenario facts.
        - `published_price` object: Fresh, rankable published price with explicitly published APY for deposits and published APR or clearly labeled nominal rate for lending, plus source evidence and per-row as_of. APR and nominal rate are never treated as interchangeable.
        - `underwriting` object, required: Explicit statement that creditworthiness and underwriting were not evaluated.
          - `status` 'not_evaluated', required: Catalog underwriting status; always not_evaluated.
          - `reason` string, required: Why no underwriting conclusion may be drawn.
        - `approval` object, required: Explicit statement that RateAPI did not evaluate or grant approval.
          - `status` 'not_evaluated_by_rateapi', required: Approval status; always not_evaluated_by_rateapi.
          - `reason` string, required: Why only the institution can approve and confirm final terms.
      - `no_published_price` AccessCatalogRow[], required: Graph-positive institutions with no matching fresh, rankable, evidenced published price; absence is not unavailability.
        - `credit_union_id` string, required: Stable credit-union identifier.
        - `institution` object, required: Institution name, state, and published URL where available.
        - `membership` object, required: Positive-evidence-only membership verdict and active-publication proof.
        - `product_availability` object, required: Whether matching fresh evidenced published pricing was found; unknown never means unavailable.
        - `product_suitability` object: Evaluation of only the explicit published constraints and supplied scenario facts.
        - `published_price` object: Fresh, rankable published price with explicitly published APY for deposits and published APR or clearly labeled nominal rate for lending, plus source evidence and per-row as_of. APR and nominal rate are never treated as interchangeable.
        - `underwriting` object, required: Explicit statement that creditworthiness and underwriting were not evaluated.
          - `status` 'not_evaluated', required: Catalog underwriting status; always not_evaluated.
          - `reason` string, required: Why no underwriting conclusion may be drawn.
        - `approval` object, required: Explicit statement that RateAPI did not evaluate or grant approval.
          - `status` 'not_evaluated_by_rateapi', required: Approval status; always not_evaluated_by_rateapi.
          - `reason` string, required: Why only the institution can approve and confirm final terms.
      - `questions` object[], required: Product-aware missing-fact questions that may clarify reachability.
      - `completeness` object, required: Exact counts and bounded-detail disclosure for this selector.
        - `active_fleet_evaluated` true, required: True only when eligibility evaluated the complete active fleet.
        - `counts_exact` true, required: Whether bucket counts were computed before detail caps.
        - `detail_limit` integer, required: Detail-row allowance remaining for this selector after global caps.
        - `details_returned` integer, required: Detail rows actually returned for this selector.
        - `details_truncated` boolean, required: Whether exact bucket counts exceed returned detail rows.
    - `questions` object, required: Membership questions shared across all selectors.
    - `snapshot` object, required: Eligibility generation boundary, returned-price observation range, and response generation time.
    - `completeness` object, required: Request-wide fleet, selector, cap, truncation, and execution-strategy disclosure.
      - `active_fleet_evaluated` true, required: True only when the complete active eligibility fleet was evaluated.
      - `candidate_set_truncated` false, required: Always false; rate intersection uses every graph-positive candidate.
      - `selector_count` integer, required: Number of explicit product selectors evaluated.
      - `selectors_explicit` true, required: Always true; RateAPI does not silently expand product families.
      - `evaluation_strategy` 'one_eligibility_discovery_then_one_batched_rate_query', required: One exhaustive eligibility evaluation followed by one semantics-preserving batched rate statement.
      - `rate_query_count` integer, required: Rate-corpus statements executed; zero when the eligibility result contains no rate candidates.
      - `proof_strategy` 'one_shared_current_publication_query', required: Eligibility proof is hydrated once against current publication lineage and shared across selectors.
      - `limit_per_product` integer, required: Maximum detail rows allocated to any selector before the request-wide cap.
      - `total_detail_limit` integer, required: Request-wide returned-detail cap; exact counts are computed before this cap.
      - `details_truncated` boolean, required: Whether any exact selector count exceeds its returned detail rows.
    - `semantics` 'positive_evidence_only', required: Interpretation contract: missing or unknown evidence never proves a negative.
    - `disclosure` string, required: Required consumer-facing distinction between access, pricing, underwriting, and approval.
  - `candidate` AccessCatalogResponse, required: One-snapshot, multi-product personal access catalog with explicit semantic layers and bounded details.
    - `catalog_version` 'access_catalog_v1', required: Stable response-contract version.
    - `products` object[], required: One result in request order for every explicit product selector.
      - `request` Product, required (unresolved $ref)
      - `ranking_basis` string, required: Published-price ordering used within this selector.
      - `ranking` object, required: Explicit declaration of the decision layers this ranking does not perform.
        - `personalized_underwriting` false, required: Always false; catalog ranking is not underwriting.
        - `approval_evaluated` false, required: Always false; RateAPI does not make approval decisions.
      - `counts` Counts, required (unresolved $ref)
      - `reachable_now` AccessCatalogRow[], required: Rows with proven present membership access, satisfied published constraints, and evidenced pricing.
        - `credit_union_id` string, required: Stable credit-union identifier.
        - `institution` object, required: Institution name, state, and published URL where available.
        - `membership` object, required: Positive-evidence-only membership verdict and active-publication proof.
        - `product_availability` object, required: Whether matching fresh evidenced published pricing was found; unknown never means unavailable.
        - `product_suitability` object: Evaluation of only the explicit published constraints and supplied scenario facts.
        - `published_price` object: Fresh, rankable published price with explicitly published APY for deposits and published APR or clearly labeled nominal rate for lending, plus source evidence and per-row as_of. APR and nominal rate are never treated as interchangeable.
        - `underwriting` object, required: Explicit statement that creditworthiness and underwriting were not evaluated.
          - `status` 'not_evaluated', required: Catalog underwriting status; always not_evaluated.
          - `reason` string, required: Why no underwriting conclusion may be drawn.
        - `approval` object, required: Explicit statement that RateAPI did not evaluate or grant approval.
          - `status` 'not_evaluated_by_rateapi', required: Approval status; always not_evaluated_by_rateapi.
          - `reason` string, required: Why only the institution can approve and confirm final terms.
      - `reachable_after_action` AccessCatalogRow[], required: Rows requiring a source-proven membership action before access.
        - `credit_union_id` string, required: Stable credit-union identifier.
        - `institution` object, required: Institution name, state, and published URL where available.
        - `membership` object, required: Positive-evidence-only membership verdict and active-publication proof.
        - `product_availability` object, required: Whether matching fresh evidenced published pricing was found; unknown never means unavailable.
        - `product_suitability` object: Evaluation of only the explicit published constraints and supplied scenario facts.
        - `published_price` object: Fresh, rankable published price with explicitly published APY for deposits and published APR or clearly labeled nominal rate for lending, plus source evidence and per-row as_of. APR and nominal rate are never treated as interchangeable.
        - `underwriting` object, required: Explicit statement that creditworthiness and underwriting were not evaluated.
          - `status` 'not_evaluated', required: Catalog underwriting status; always not_evaluated.
          - `reason` string, required: Why no underwriting conclusion may be drawn.
        - `approval` object, required: Explicit statement that RateAPI did not evaluate or grant approval.
          - `status` 'not_evaluated_by_rateapi', required: Approval status; always not_evaluated_by_rateapi.
          - `reason` string, required: Why only the institution can approve and confirm final terms.
      - `unresolved` AccessCatalogRow[], required: Rows that cannot be promoted because membership proof or product suitability remains unresolved.
        - `credit_union_id` string, required: Stable credit-union identifier.
        - `institution` object, required: Institution name, state, and published URL where available.
        - `membership` object, required: Positive-evidence-only membership verdict and active-publication proof.
        - `product_availability` object, required: Whether matching fresh evidenced published pricing was found; unknown never means unavailable.
        - `product_suitability` object: Evaluation of only the explicit published constraints and supplied scenario facts.
        - `published_price` object: Fresh, rankable published price with explicitly published APY for deposits and published APR or clearly labeled nominal rate for lending, plus source evidence and per-row as_of. APR and nominal rate are never treated as interchangeable.
        - `underwriting` object, required: Explicit statement that creditworthiness and underwriting were not evaluated.
          - `status` 'not_evaluated', required: Catalog underwriting status; always not_evaluated.
          - `reason` string, required: Why no underwriting conclusion may be drawn.
        - `approval` object, required: Explicit statement that RateAPI did not evaluate or grant approval.
          - `status` 'not_evaluated_by_rateapi', required: Approval status; always not_evaluated_by_rateapi.
          - `reason` string, required: Why only the institution can approve and confirm final terms.
      - `no_published_price` AccessCatalogRow[], required: Graph-positive institutions with no matching fresh, rankable, evidenced published price; absence is not unavailability.
        - `credit_union_id` string, required: Stable credit-union identifier.
        - `institution` object, required: Institution name, state, and published URL where available.
        - `membership` object, required: Positive-evidence-only membership verdict and active-publication proof.
        - `product_availability` object, required: Whether matching fresh evidenced published pricing was found; unknown never means unavailable.
        - `product_suitability` object: Evaluation of only the explicit published constraints and supplied scenario facts.
        - `published_price` object: Fresh, rankable published price with explicitly published APY for deposits and published APR or clearly labeled nominal rate for lending, plus source evidence and per-row as_of. APR and nominal rate are never treated as interchangeable.
        - `underwriting` object, required: Explicit statement that creditworthiness and underwriting were not evaluated.
          - `status` 'not_evaluated', required: Catalog underwriting status; always not_evaluated.
          - `reason` string, required: Why no underwriting conclusion may be drawn.
        - `approval` object, required: Explicit statement that RateAPI did not evaluate or grant approval.
          - `status` 'not_evaluated_by_rateapi', required: Approval status; always not_evaluated_by_rateapi.
          - `reason` string, required: Why only the institution can approve and confirm final terms.
      - `questions` object[], required: Product-aware missing-fact questions that may clarify reachability.
      - `completeness` object, required: Exact counts and bounded-detail disclosure for this selector.
        - `active_fleet_evaluated` true, required: True only when eligibility evaluated the complete active fleet.
        - `counts_exact` true, required: Whether bucket counts were computed before detail caps.
        - `detail_limit` integer, required: Detail-row allowance remaining for this selector after global caps.
        - `details_returned` integer, required: Detail rows actually returned for this selector.
        - `details_truncated` boolean, required: Whether exact bucket counts exceed returned detail rows.
    - `questions` object, required: Membership questions shared across all selectors.
    - `snapshot` object, required: Eligibility generation boundary, returned-price observation range, and response generation time.
    - `completeness` object, required: Request-wide fleet, selector, cap, truncation, and execution-strategy disclosure.
      - `active_fleet_evaluated` true, required: True only when the complete active eligibility fleet was evaluated.
      - `candidate_set_truncated` false, required: Always false; rate intersection uses every graph-positive candidate.
      - `selector_count` integer, required: Number of explicit product selectors evaluated.
      - `selectors_explicit` true, required: Always true; RateAPI does not silently expand product families.
      - `evaluation_strategy` 'one_eligibility_discovery_then_one_batched_rate_query', required: One exhaustive eligibility evaluation followed by one semantics-preserving batched rate statement.
      - `rate_query_count` integer, required: Rate-corpus statements executed; zero when the eligibility result contains no rate candidates.
      - `proof_strategy` 'one_shared_current_publication_query', required: Eligibility proof is hydrated once against current publication lineage and shared across selectors.
      - `limit_per_product` integer, required: Maximum detail rows allocated to any selector before the request-wide cap.
      - `total_detail_limit` integer, required: Request-wide returned-detail cap; exact counts are computed before this cap.
      - `details_truncated` boolean, required: Whether any exact selector count exceeds its returned detail rows.
    - `semantics` 'positive_evidence_only', required: Interpretation contract: missing or unknown evidence never proves a negative.
    - `disclosure` string, required: Required consumer-facing distinction between access, pricing, underwriting, and approval.
  - `deltas` object, required: Per-product and portfolio changes using stable credit-union/product row ids and membership proof references.
    - `products` object[]: Selector-aligned changes; identity churn is scoped to returned detail rows while reachable_now_counts is exact.
      - `reachable_now_counts` AccessCatalogReachableNowCounts: Exact reachable-now product-offer row counts sourced from catalog counts, independent of returned detail caps.
        - `baseline` integer, required: Exact baseline reachable-now count.
        - `candidate` integer, required: Exact candidate reachable-now count.
        - `net` integer, required: Candidate minus baseline exact reachable-now count.
        - `unit` 'product_offer_rows', required: Counts product-selector offer rows, not unique institutions or identity churn.
        - `exact` true, required: Always true because values come from exact catalog counts.
      - `best_published_price` object: Like-for-like price comparison. Deposit sides both use APY. Lending sides both use APR when present on both sides, otherwise both use nominal rate; if no common measure exists, both prices and the basis-point delta are null.
    - `portfolio` object: Cross-selector totals in product-offer rows.
      - `reachable_now_counts` AccessCatalogReachableNowCounts: Exact reachable-now product-offer row counts sourced from catalog counts, independent of returned detail caps.
        - `baseline` integer, required: Exact baseline reachable-now count.
        - `candidate` integer, required: Exact candidate reachable-now count.
        - `net` integer, required: Candidate minus baseline exact reachable-now count.
        - `unit` 'product_offer_rows', required: Counts product-selector offer rows, not unique institutions or identity churn.
        - `exact` true, required: Always true because values come from exact catalog counts.
    - `completeness` object: Whether returned-detail identity churn is exhaustive or cap-scoped.
  - `snapshot` object, required: One pinned rules_now and immutable graph generation; rate rows retain independent as_of.
  - `semantics` 'positive_evidence_only', required: Only positive evidence promotes access; absence is not denial.
  - `disclosure` string, required: Required limits on savings, underwriting, approval, denial, and final-term interpretations.

## Other responses

- `400`: The request was malformed — a missing required field, an unparseable body, or a parameter outside its allowed range. The `error` field names what was wrong; retrying the identical request will fail identically.
- `401`: No API key, or a key that is unknown or disabled. Send it in the `X-API-Key` header. Free keys are issued instantly by POST /keys with an email address. The response carries `WWW-Authenticate` pointing at this host's protected-resource metadata, and the `RateLimit-*` headers describing the Free-tier budget a key issued now would carry (scope `anonymous`) — a rejected request spends none of it, so `Remaining` equals `Limit`.
- `402`: The key is valid, but RateAPI Routes is available only on Enterprise. The response includes `required_plan`, `upgrade_url`, and a `Link` header with `rel="upgrade"`; the rejected request does not consume quota.
- `429`: Quota exhausted for the current window. `Retry-After` gives the seconds to wait; `upgradeInfo` explains how to lift the cap. Retrying before the reset will fail again and still counts as a request.
- `503`: A required serving dependency is temporarily unavailable. This is not a negative eligibility or product decision; retry with backoff or continue using confirmed direct fields on deterministic endpoints.

---

[API](https://skmtc.dev/rateapi/apis/rate-api.md) · [All operations](https://skmtc.dev/rateapi/apis/rate-api/llms.txt) · [OpenAPI document](https://skmtc.dev/rateapi/apis/rate-api/revisions/06a6db76995f?raw)
