> Fetch https://askmiles.ai/llms.txt first: it indexes every public Miles capability. This file is the markdown twin of https://askmiles.ai/docs/catalog/endpoints.

# Catalog endpoints

The free, keyless catalog API: credit card, transfer partner, and point valuation data.

### GET /health

Confirms the worker can reach its data store. Not under /v1/public — the router only rewrites /v1/public/* paths, so /v1/health 404s; use this exact URL (or /api/health, an alias).

```bash
curl "https://api.askmiles.ai/health"
```

Response:

```json
{
  "status": "healthy",
  "data_available": true,
  "environment": "production",
  "timestamp": "2026-08-14T20:03:10.814Z"
}
```

### GET /public/credit-cards

Every open card, alphabetical by name. Filter with search, issuer, card_type, or network.

```bash
curl "https://api.askmiles.ai/v1/public/credit-cards"
```

Response:

```json
[
  {
    "id": "chase-sapphire-preferred-credit-card",
    "card_name": "Chase Sapphire Preferred Credit Card",
    "display_name": "Sapphire Preferred",
    "issuer": "Chase",
    "card_type": "Personal",
    "network": "Visa",
    "card_network_tier": "Visa Signature",
    "annual_fee": 95,
    "foreign_transaction_fee": 0,
    "rewards_currency": "Chase Ultimate Rewards",
    "welcome_offer_available": true,
    "has_statement_credits": true,
    "credit_types": ["Global Entry / TSA PreCheck / NEXUS Credit", "..."],
    "lounge_networks": [],
    "protections": ["Purchase Protection", "..."],
    "has_elite_status_benefits": false,
    "has_free_night_certificate": false,
    "family": {
      "family_name": "Chase Ultimate Rewards Personal",
      "tier_name": "Sapphire Preferred",
      "can_upgrade": true,
      "can_downgrade": true
    }
  }
]
```

family is present only on cards that belong to one.

### GET /public/credit-cards/{cardId}

The id is the same URL-safe slug the list endpoint returns, not the card's display name.

```bash
curl "https://api.askmiles.ai/v1/public/credit-cards/chase-sapphire-preferred-credit-card"
```

Response:

```json
{ "id": "chase-sapphire-preferred-credit-card", "...": "same shape as the list endpoint's rows" }
```

404s as {"error": "Card not found"} for an unknown or closed card — a closed card’s id simply isn’t in this dataset.

### POST /public/credit-cards/search

Same card rows as the list endpoint, filtered by a JSON body instead of query params. An empty body {} returns the same set as the list endpoint.

```bash
curl -X POST "https://api.askmiles.ai/v1/public/credit-cards/search" \
  -H "Content-Type: application/json" \
  -d '{"issuer":"Chase","annual_fee_max":100,"no_foreign_fee":true,"limit":25}'
```

Response:

```json
[ { "id": "amazon-prime-visa-card", "...": "same row shape as the list endpoint" } ]
```

### POST /public/benefits-search

Free-text match against benefit names — lounge programs, credits, protections. query is required.

```bash
curl -X POST "https://api.askmiles.ai/v1/public/benefits-search" \
  -H "Content-Type: application/json" \
  -d '{"query":"lounge access","limit":10}'
```

Response:

```json
[
  {
    "id": "the-platinum-card-from-american-express",
    "card_name": "The Platinum Card from American Express",
    "display_name": "Amex Platinum",
    "issuer": "American Express",
    "annual_fee": 895,
    "matched_benefits": [
      "Lounge: American Express Centurion Lounge",
      "Lounge: Priority Pass Select",
      "..."
    ]
  }
]
```

### GET /public/transfer-partners

Every bank-to-loyalty-program transfer route: which ones exist and which are live. Ratios, bonus size and expiry aren't in the free schema. active_only defaults to true.

```bash
curl "https://api.askmiles.ai/v1/public/transfer-partners?has_bonus=true"
```

Response:

```json
{
  "source_program": "American Express Membership Rewards",
  "dest_program": "Aer Lingus AerClub",
  "is_active": true,
  "has_transfer_bonus": true
}
```

### GET /public/transfer-partners/from/{sourceProgram}

Every destination program reachable from one source. URL-encode the program name; 404s if the source program is unrecognized.

```bash
curl "https://api.askmiles.ai/v1/public/transfer-partners/from/Chase%20Ultimate%20Rewards"
```

Response:

```json
[ { "source_program": "Chase Ultimate Rewards", "dest_program": "Emirates Skywards", "is_active": false, "deactivated_date": "2025-06-30" } ]
```

### GET /public/transfer-partners/to/{destProgram}

Every source program that can transfer into one destination. Same encoding and 404 behavior as the from/ route.

```bash
curl "https://api.askmiles.ai/v1/public/transfer-partners/to/United%20MileagePlus"
```

Response:

```json
[ { "source_program": "Bilt Rewards", "dest_program": "United MileagePlus", "is_active": true, "has_transfer_bonus": false } ]
```

### GET /public/valuations

Current cents-per-point value for every tracked currency. programs filters to a comma-separated list of program keys or display names.

```bash
curl "https://api.askmiles.ai/v1/public/valuations"
```

Response:

```json
{
  "version": "1.0",
  "unit": "cents_per_point",
  "valuations": {
    "chase_ultimate_rewards": {
      "value": 1.5,
      "display_name": "Chase Ultimate Rewards",
      "category": "transferable"
    }
  },
  "updated_at": "2026-08-03T20:00:50.826842+00:00",
  "rrv_last_sync": "2026-07-11T03:00:20.750622+00:00",
  "created_at": "2026-08-03T19:54:21.300771+00:00"
}
```

category is one of transferable, airline, hotel, restricted, or other — restricted marks a cash-like currency with redemption limits (e.g. Bilt Cash); everything else is a regular transferable, airline, or hotel currency, or other for a program that fits none of those.

### GET /public/exports/status

Size and last-modified time for each full-dataset export. /public/exports (no /status) returns the identical payload. Not in openapi.yaml.

```bash
curl "https://api.askmiles.ai/v1/public/exports/status"
```

Response:

```json
{
  "datasets": {
    "credit_cards": {
      "available": true,
      "size_bytes": 180063,
      "last_modified": "2026-08-14T20:01:28.333Z",
      "download_url": "/api/public/exports/credit_cards"
    }
  },
  "last_sync": "2026-08-14T20:01:28.672Z"
}
```

### GET /public/exports/credit_cards

credit_cards, transfer_partners, or valuations. Unlike every other endpoint here, the response is NOT unwrapped — it's the raw R2 file, envelope included. GET only; a HEAD request 404s. Not in openapi.yaml.

```bash
curl "https://api.askmiles.ai/v1/public/exports/credit_cards"
```

Response:

```json
{
  "version": "2026-08-14T20:01:28.090722+00:00",
  "checksum": "9a50ebfb1603e604",
  "count": 186,
  "data": [ { "id": "aadvantage-business-world-elite-mastercard", "...": "..." } ]
}
```

### POST /mcp

The same free-schema catalog, spoken as Model Context Protocol so an agent can call it without a hand-written client. Keyless like the rest of this API, and unrelated to mcp.askmiles.ai, which is account-scoped and requires OAuth. Five read-only tools: search_card_catalog, get_card_facts, compare_card_facts, find_transfer_routes, estimate_point_value. Handshake revisions 2024-11-05 through 2025-11-25 and the modern 2026-07-28 envelope both work; GET and DELETE return 405, and responses are no-store. Not in openapi.yaml.

```bash
curl -X POST "https://api.askmiles.ai/mcp" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"search_card_catalog","arguments":{"issuer":"Chase","no_foreign_transaction_fee":true}}}'
```

Response:

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "resultType": "complete",
    "content": [
      { "type": "text", "text": "{ \"cards\": [ ... ], \"miles\": { ... } }" },
      { "type": "text", "text": "Not in this answer: how much each card earns per category; ..." }
    ],
    "structuredContent": {
      "cards": [ { "id": "chase-sapphire-preferred", "...": "..." } ],
      "matched_count": 3,
      "miles": { "source": "Miles · askmiles.ai — ...", "full_answer": "https://askmiles.ai/try?prefill=..." }
    }
  }
}
```

Every successful result carries a `miles` object naming what the catalog could not answer, and a link to Miles' own chat. Point valuations in these results are Miles' estimates, not market prices.
