Card data for bloggers, newsletters and creators
Card content goes stale the day an issuer changes an offer. CardAPI tells you what changed and when, so a review, a newsletter or a best-cards page shows today's numbers.
The plan you need
Pro plan and abovePro ($79/mo) returns every field and endpoint below.
Prototype on the Free plan: it returns each card's basic fields and top 3 reward rates. See what each plan returns.
Fields
- name
- annual_fee
- signup_bonus
- signup_bonus_points
- signup_min_spend
- historical_best_offer
- historical_best_offer_date
Types and descriptions: the card object.
Endpoints
- GET /v1/offers/notable — List notable offer changes
- GET /v1/cards/:slug — Get a card
Going further
- A webhook the moment a card's offer or fee changesPOST /v1/webhooksEnterprise plan
- The full change log of one cardGET /v1/cards/:slug/historyPro plan and above
Displaying and caching the data
- Articles, videos and other editorial content you publish while your plan allows it may stay up after the plan ends; just don't update them with data fetched after that without an active plan.
- Quote the offers in your own words and tables; don't publish the raw data as a download or a feed.
- Data fetched during the Starter trial is for evaluation only until the trial becomes a paid plan: build and test on it, publish once the plan is paid.
- Cache what you fetch for as long as your plan is active (ISR, a database, a KV store); re-fetch on a schedule so changes reach your users. The data is re-checked against issuer sites every Friday, so a daily or weekly refresh is plenty.
The full rules are in the Terms of Service.
Code
Runs on your own key (CARDAPI_API_KEY) and fetches at runtime: nothing here ships card data. Uses @cardapi/client 0.4.0 or later.
npm install @cardapi/client
import { CardAPI } from "@cardapi/client";
const api = new CardAPI({ apiKey: process.env.CARDAPI_API_KEY! });
export async function offerDigest(country: "US" | "CA" = "US") {
const weekAgo = Date.now() - 7 * 24 * 60 * 60 * 1000;
const changes = await api.getNotableOffers(country);
return changes
.filter((c) => new Date(c.detected_at).getTime() >= weekAgo)
.map((c) => `${c.card_name}: ${c.field_name} ${c.old_value ?? "none"} -> ${c.new_value ?? "none"}`);
}