API profiles

Every API is a normalized row with verification and live health — not just a link.

Endpoints

bash
GET /v1/categories/:id/apis?page=1&limit=20   # list in category (slug)
GET /v1/apis/:slug                         # full profile (ETag → 304)
GET /v1/apis/:id/alternatives?limit=3      # similar APIs
GET /v1/apis/:id/health-check              # POST trigger (auth, cooldown + 429)
GET /v1/apis/:id/health-checks/:checkId    # poll result

Profile shape (selected)

json
{
  "id": "…", "slug": "open-meteo", "name": "Open-Meteo",
  "description": "…", "link": "https://api.open-meteo.com", "documentationUrl": "https://open-meteo.com/...",
  "category": { "name": "Weather", "slug": "weather" },
  "auth": "No", "pricing": "Free", "rateLimitText": "10k/day",
  "corsStatus": "Yes", "httpsSupport": true, "responseFormats": ["JSON"], "sdkLanguages": [],
  "isAlive": true, "responseTime": 184, "statusCode": 200, "lastChecked": "2026-09-04T…Z",
  "trustScore": { "score": 86, "grade": "B", "factors": { "uptime": 0.9, "docs": 0.8 } },
  "verification": [{ "field": "docs", "source": "AUTOMATED_CHECK", "confidence": 0.9 }],
  "warnings": [], "updatedAt": "2026-09-04T…Z"
}

On the web

Web: reqistry.dev/apis/<slug> renders the same profile with trust score, capabilities, health history, verification stamps, warnings, and an alternatives strip. Category pages (/categories/<slug>) paginate via GET /v1/categories/:id/apis.

Health

Workers: HEAD → fallback GET, 10s timeout, writes api_health_checks + upserts api_current_health (uptime24h/7d/30d, consecutiveFailures). Trigger is auth-gated with cooldown; poll via /health-checks/:checkId. Public profiles expose the last check; no need to poll to read.