← back

JSON API

Plain static JSON files served from CloudFront. CORS is enabled (Access-Control-Allow-Origin: *). Refreshed by the collector Lambda 4× daily; CloudFront cache TTL is 5 minutes.

/api/models.json

Full normalized list, one entry per (provider, model). Each entry has a canonicalId you can use to join across providers.

Array<{
  canonicalId: string,
  provider: "bedrock" | "vertex" | "openrouter",
  providerModelId: string,
  displayName: string,
  family: string,
  publisher?: string,
  modality?: string[],
  contextWindow?: number,
  pricingStatus: "known" | "unknown",
  pricingInputPer1M?: number,
  pricingOutputPer1M?: number,
  pricingCurrency?: "USD",
  available: boolean,
  region?: string,
  firstSeenAt: string,
  lastSeenAt: string
}>
/api/models-by-provider.json

Same data, pre-grouped by provider. Faster than filtering models.json yourself.

{
  bedrock: Model[],
  vertex: Model[],
  openrouter: Model[]
}
/api/models-by-family.json

Same data, pre-grouped by detected family (claude, gemini, qwen, deepseek, kimi, …). Use the family key "other" for long-tail models that don't match a known family.

{
  claude: Model[],
  gemini: Model[],
  qwen: Model[],
  /* … */
}
/api/diff-latest.json

Models added/removed since the previous run. Available after Phase 6 lands.

{
  added: Model[],
  removed: Model[],
  since: string  // ISO timestamp
}
/api/meta.json

Collection metadata.

{
  lastRun: string,    // ISO timestamp
  counts: { bedrock, vertex, openrouter, total },
  schemaVersion: "1"
}

Examples

# every Claude model and where it is
curl -s https://models.apresai.dev/api/models.json \
  | jq '.[] | select(.family == "claude") | {provider, providerModelId, in: .pricingInputPer1M}'

# everything currently on Bedrock
curl -s https://models.apresai.dev/api/models-by-provider.json | jq .bedrock

# is "kimi-k2" available anywhere right now?
curl -s https://models.apresai.dev/api/models.json \
  | jq '[.[] | select(.canonicalId | test("kimi-k2"))] | map(.provider) | unique'