Reward rates API
Every planFree keys get each card's 3 highest rates; Starter and above get every rate.
Every card carries its reward rates: how much it earns in each spending category, with any cap, merchant limit or travel-portal condition. GET /v1/cards/best ranks cards by what they earn in one category, and GET /v1/categories lists the categories you can ask for.
A rate's categories are slugs from /v1/categories. Its category_slug is a label built from them that is unique on the card: <categories>[:<merchant>][@portal|@direct][#choice][~<tag>], for example dining, groceries+gas, airlines:united-airlines, travel@portal or dining#choice. The base rate is other.
Endpoints
GET /v1/cards/best: Rank cards for a category
Cards ranked by their reward rate in one spending category. Each card carries a category_rate object with the matching rate. Rates are matched on their canonical categories; merchant-only, portal-only and pick-your-category rates, and discontinued cards, are left out unless you opt in.
categorystringrequiredCategory slug, e.g. dining, groceries, gas, travel (see /v1/categories); a reward rate's category_slug naming one category also works (dining#choice, travel@portal)countrystringUS or CAmax_annual_feenumberHighest annual fee to includeno_annual_feebooleantrue for cards with a stated $0 annual fee only (an unknown fee does not count)include_restrictedbooleantrue to also rank rates limited to one merchant, the issuer's travel portal, or a pick-your-category option (e.g. Citi Custom Cash)include_discontinuedbooleantrue to also rank cards no longer open to new applicantslimitintegerNumber of results (default 10, max 50)curl "https://api.cardapi.dev/v1/cards/best?category=dining&country=US" \-H "Authorization: Bearer YOUR_API_KEY"
{
"data": [
{
"slug": "citi-strata-elite-card",
"name": "Citi Strata Elite Card",
"annual_fee": 595,
"category_rate": {
"category_slug": "dining",
"categories": ["dining"],
"rate_multiplier": 6,
"rate_type": "multiplier",
"cap_amount": null,
"cap_period": null,
"merchant": null,
"booking_channel": null,
"choice_group": null,
"is_rotating": false
}
},
{
"slug": "ihg-one-rewards-premier-credit-card",
"name": "IHG One Rewards Premier Credit Card",
"annual_fee": 99,
"category_rate": {
"category_slug": "dining",
"categories": ["dining"],
"rate_multiplier": 5,
"rate_type": "points_per_dollar",
"cap_amount": null,
"cap_period": null,
"merchant": null,
"booking_channel": null,
"choice_group": null,
"is_rotating": false
}
}
]
}GET /v1/categories: List spending categories
The spending categories CardAPI tracks. Use their slugs with /v1/cards/best. Every reward rate's categories come from this list, and its category_slug label starts with them, joined by + in this list's order (groceries+gas).
curl "https://api.cardapi.dev/v1/categories" \-H "Authorization: Bearer YOUR_API_KEY"
{
"data": [
{ "slug": "groceries", "name": "Groceries", "icon": "shopping-cart", "sort_order": 1 },
{ "slug": "gas", "name": "Gas & Fuel", "icon": "fuel", "sort_order": 2 },
{ "slug": "dining", "name": "Dining", "icon": "utensils", "sort_order": 3 },
{ "slug": "travel", "name": "Travel", "icon": "plane", "sort_order": 4 },
{ "slug": "drugstore", "name": "Drugstore", "icon": "pill", "sort_order": 5 },
{ "slug": "entertainment", "name": "Entertainment", "icon": "film", "sort_order": 6 },
{ "slug": "streaming", "name": "Streaming", "icon": "tv", "sort_order": 7 },
{ "slug": "transit", "name": "Transit", "icon": "bus", "sort_order": 8 },
{ "slug": "online-shopping", "name": "Online Shopping", "icon": "globe", "sort_order": 9 },
{ "slug": "other", "name": "Other / General", "icon": "credit-card", "sort_order": 10 }
]
}Reward rate fields
| Field | Type | Description |
|---|---|---|
id | string (uuid) | |
card_id | string (uuid) | |
category_slug | stringnullable | Label for the rate, unique on its card within a rotating quarter and built from the fields beside it, so the same rate has the same label on every card: <categories>[:<merchant>][@portal|@direct][#choice][~<tag>]. categories: the rate's `categories` joined by "+" in /v1/categories order ("groceries+gas"); a base rate is "other". :<merchant>: the merchant it is limited to, slugged ("airlines:united-airlines", "other:best-buy"). @portal / @direct: booking_channel issuer_portal / direct ("travel@portal"). #choice: one of a pick-your-category group ("dining#choice"). ~<tag>: only when two rates of one card would otherwise share a label, e.g. "airlines:united-airlines~3x"; a tag can change when the card's other rates change. Match on `categories`, `merchant`, `booking_channel` and `choice_group`, not by parsing the label. |
categories | string[] | Canonical categories this rate applies to; every value is a slug from GET /v1/categories. A rate can cover several (e.g. gas and groceries under one cap). |
merchant | stringnullable | Merchant or co-brand partner the rate is limited to (e.g. "Best Buy", "United Airlines"). Null when it applies anywhere in the category. |
booking_channel | stringnullable | issuer_portal: only when booked through the issuer's travel portal (Chase Travel, Capital One Travel, ...). direct: booked directly with the airline or hotel. |
choice_group | stringnullable | Rates on one card that share a choice_group are alternatives (pick-your-category cards): only choice_picks of them earn at once. |
choice_picks | integernullable | How many categories in the choice_group earn the rate at the same time. |
choice_selection | stringnullable | user: the cardholder picks; automatic: applied to the top spend categories. |
rate_multiplier | number | |
rate_type | string | |
cap_amount | numbernullable | |
cap_period | stringnullable | |
fallback_rate | numbernullable | |
is_base_rate | boolean | |
is_rotating | boolean | True for a quarterly rotating bonus row; see rotating_quarter/rotating_year. |
rotating_quarter | integernullable | |
rotating_year | integernullable | |
notes | stringnullable | |
created_at | string (date-time) |