import type { Metadata } from 'next'; import Link from 'next/link'; import { BreadcrumbLd } from '@/components/meta/breadcrumb-ld'; import { DataTable, Td, Th } from '@/components/ui/data-table'; import { Container, Note, PageHeader, Section } from '@/components/ui/section'; import { Unavailable } from '@/components/ui/unavailable'; import { api, safe } from '@/lib/api'; import { PUBLIC_API_BASE, routes, SITE_NAME } from '@/lib/site'; import type { Stats } from '@/lib/types'; import { RequestBuilder } from './request-builder'; import { ROUTES } from './routes'; export const metadata: Metadata = { title: 'Developers — public API 1.1, request builder, provenance and history recipes', description: 'The AI Atlas public API: JSON over HTTPS, no key for public routes, OpenAPI docs, an interactive request builder with curl / Python / JavaScript snippets, and recipes for pagination, provenance and historical queries.', alternates: { canonical: '/developers' } }; export const revalidate = 3600; /** Compact, honest projection of /stats for the example block (the real payload has more counters). */ function statsExample(s: Stats) { return { entities: s.entities, entities_total: s.entities_total, organizations_total: s.organizations_total, change_events_live_24h: s.change_events_live_24h, claims_current: s.claims_current, prices_current: s.prices_current, last_event_at: s.last_event_at, definitions: s.definitions ? `${Object.keys(s.definitions).length} counter definitions` : undefined, computed_at: s.computed_at, '…': `${Object.keys(s).length} keys in total` }; } function Code({ children }: { children: string }) { return (
{children}
);
}
export default async function DevelopersPage() {
const [health, stats, top] = await Promise.all([safe(api.health()), safe(api.stats()), safe(api.models({ limit: 1, sort: 'quality' }))]);
const exA = top?.items[0]?.slug ?? 'API status unavailable
} />Interactive OpenAPI documentation: /api/v1/docs. JSON, UTF-8, ISO-8601 UTC timestamps. Errors are {'{ "detail": "…" }'} with 400 / 404 / 409 / 429 / 501 / 503 (422 with errors for parameters rejected by validation). Every response carries x-api-version: 1.1.
Cursor pagination on feeds
{`# /changes and /entities/{slug}/timeline return next_before; pass it back as before=
curl -s "${PUBLIC_API_BASE}/changes?importance_min=2&limit=50" | jq '{next_before, n: (.items|length)}'
curl -s "${PUBLIC_API_BASE}/changes?importance_min=2&limit=50&before="
# Listings use limit/offset (≤ 200; /sitemap ≤ 5 000). 1.1 feeds are keyed on occurred_at and exclude backfill:
curl -s "${PUBLIC_API_BASE}/changes?include_backfill=1&date_field=observed&limit=20" # v1 behaviour`}
Field-level provenance
{`# Every displayed value has a claim behind it
curl -s "${PUBLIC_API_BASE}/entities/${exA}/provenance/context_length" | jq '{value, source: .source.name, tier, extractor, observed_at, valid_since, claim_id, conflicts: (.conflicts|length)}'
# One claim and its lifecycle (previous, superseding, conflicting)
curl -s "${PUBLIC_API_BASE}/claims/" | jq '{property, claim: .claim.value, chain: (.chain | map_values(if type=="array" then length else . end))}'
# All current claims of an entity
curl -s "${PUBLIC_API_BASE}/entities/${exA}/claims?status=current&limit=50" | jq '.items[] | {property, value, tier, source_name}'`}
Historical queries
{`# The atlas as of a date (reconstructed before the observation history)
curl -s "${PUBLIC_API_BASE}/time-machine?date=2025-06-01&scope=models&limit=20" | jq '{reconstructed, first_entity_at, total: .models.total}'
# One entity as of a date, and the full claim history of a property
curl -s "${PUBLIC_API_BASE}/entities/${exA}/asof?date=${weekAgo}" | jq '{existed, attributes}'
curl -s "${PUBLIC_API_BASE}/entities/${exA}/history?property=context_length" | jq '.items[] | {value, status, valid_from, valid_to}'
# What changed between two dates (scope: all | models | org: | family:)
curl -s "${PUBLIC_API_BASE}/diff?a=${weekAgo}&b=${today}&scope=models" | jq '.counts'
# Today in AI 2.0 — grouped sections, backfill excluded
curl -s "${PUBLIC_API_BASE}/changes/daily?date=${today}" | jq '{total, backfill_excluded, sections: [.today[] | {key, total}]}'`}
Graph
{`# Typed neighbourhood explorer — never more than limit nodes, truncated says when the API cut
curl -s "${PUBLIC_API_BASE}/graph/explore?node=anthropic&mode=company&depth=1&limit=150" | jq '{truncated, counts, predicates}'`}
{JSON.stringify(statsExample(stats), null, 2)} :