Add AI Service Status to Your App
Show live status of OpenAI, Anthropic, Groq, and 75+ AI services in your own product. Free Prismix API, no auth, three integration patterns.
Why add AI status to your UI?
If your product calls the OpenAI or Anthropic API, users will hit degraded experiences during outages. Without proactive status messaging:
- Users assume your product is broken (not the underlying AI service)
- Support tickets spike for issues you can't fix
- Trust erodes even though the failure is outside your control
Showing "OpenAI is currently degraded — AI features may be slower than normal" in your UI converts a mystery failure into a transparent, trustworthy experience.
Option 1 — Embed a badge (30 seconds)
Fastest path: drop a live SVG badge anywhere. No JavaScript, no polling. Just an <img> tag.
<!-- In your status footer, about page, or docs -->
<img src="https://prismix.dev/api/badge/openai.svg"
alt="OpenAI API status" />
<!-- Dark variant for dark backgrounds -->
<img src="https://prismix.dev/api/badge/openai.svg?theme=dark"
alt="OpenAI API status (dark)" /> Cached 30s at Cloudflare edge. Full badge guide →
Option 2 — Fetch live JSON (recommended)
Fetch https://prismix.dev/api/v1/statuses and render status inline. No API key, no auth, 60-second edge cache.
React / Next.js
import { useEffect, useState } from 'react'
const INDICATOR_COLORS = {
none: 'text-green-600',
minor: 'text-yellow-600',
major: 'text-orange-600',
critical: 'text-red-600',
unknown: 'text-gray-500',
}
export function AIStatusBanner({ services = ['openai', 'anthropic'] }) {
const [statuses, setStatuses] = useState({})
useEffect(() => {
fetch('https://prismix.dev/api/v1/statuses')
.then(r => r.json())
.then(data => {
const map = {}
for (const svc of data.services) {
if (services.includes(svc.id)) map[svc.id] = svc
}
setStatuses(map)
})
.catch(() => {}) // silent — don't break the UI on status API failure
}, [])
const degraded = Object.values(statuses).filter(s => s.indicator !== 'none')
if (!degraded.length) return null
return (
<div className="rounded-md border border-yellow-200 bg-yellow-50 px-4 py-3 text-sm">
<strong>AI service notice:</strong>{' '}
{degraded.map(s => s.name).join(', ')} may be experiencing issues.{' '}
<a href="https://prismix.dev/status" className="underline" target="_blank" rel="noopener">
Live status →
</a>
</div>
)
} Vue 3 (Composition API)
<script setup>
import { ref, onMounted } from 'vue'
const services = ref([])
onMounted(async () => {
try {
const { services: all } = await fetch('https://prismix.dev/api/v1/statuses').then(r => r.json())
services.value = all.filter(s => ['openai', 'anthropic', 'groq'].includes(s.id))
} catch {}
})
const degraded = computed(() => services.value.filter(s => s.indicator !== 'none'))
</script>
<template>
<div v-if="degraded.length" class="ai-status-banner">
AI notice: {{ degraded.map(s => s.name).join(', ') }} may be degraded.
<a href="https://prismix.dev/status" target="_blank">Live status →</a>
</div>
</template> Vanilla JS
async function checkAIStatus(serviceIds = ['openai', 'anthropic']) {
try {
const { services } = await fetch('https://prismix.dev/api/v1/statuses').then(r => r.json())
return services.filter(s => serviceIds.includes(s.id))
} catch {
return []
}
}
// Usage
const relevant = await checkAIStatus(['openai', 'anthropic'])
const degraded = relevant.filter(s => s.indicator !== 'none')
if (degraded.length) {
const banner = document.createElement('div')
banner.className = 'ai-status-banner'
banner.innerHTML = `AI notice: ${degraded.map(s => s.name).join(', ')} may be degraded.
<a href="https://prismix.dev/status">Check status →</a>`
document.body.prepend(banner)
} Option 3 — Server-side check + conditional UI
For SSR frameworks (Next.js App Router, Astro, Nuxt), fetch status at render time and conditionally show a banner. This avoids client-side flicker.
Next.js App Router (Server Component)
// app/components/AIStatusBanner.tsx (Server Component)
async function getAIStatus() {
try {
const res = await fetch('https://prismix.dev/api/v1/statuses', {
next: { revalidate: 60 }, // ISR: revalidate every 60s
})
const { services } = await res.json()
return services.filter((s) => ['openai', 'anthropic'].includes(s.id))
} catch {
return []
}
}
export default async function AIStatusBanner() {
const services = await getAIStatus()
const degraded = services.filter((s) => s.indicator !== 'none')
if (!degraded.length) return null
return (
<div className="rounded border border-amber-200 bg-amber-50 px-4 py-2 text-sm text-amber-900">
⚠️ {degraded.map((s) => s.name).join(', ')} may be experiencing issues.{' '}
<a href="https://prismix.dev/status" className="font-medium underline">
Live status
</a>
</div>
)
} Response shape reference
{
"fetchedAt": "2026-06-12T10:00:00.000Z",
"cached": true,
"services": [
{
"id": "openai",
"name": "OpenAI",
"indicator": "none", // none | minor | major | critical | unknown
"description": "All Systems Operational",
"reachable": true,
"activeIncidents": 0,
"uptime30dPct": 99.8,
"recentIncidents30d": 2,
"lastIncidentAt": "2026-05-28T14:23:00Z",
"recentIncidentBriefs": [
{
"id": "abc123",
"name": "Elevated API latency",
"impact": "minor",
"createdAt": "2026-05-28T14:00:00Z",
"resolvedAt": "2026-05-28T16:30:00Z"
}
]
}
]
} Caching and polling best practices
- The Prismix API is already cached 60 seconds at the edge — polling it faster wastes requests without getting fresher data.
- For SSR, use framework-level revalidation (Next.js
revalidate: 60, Astro server output). - For client-side polling,
setInterval(check, 60_000)is a reasonable cadence. - Always wrap the fetch in try/catch — don't let a status API failure break your UI.
- Show the banner only when
indicator !== 'none'. Show nothing during operational periods.
Subscribe your own users to AI status alerts
Instead of building your own alerting system, link your users to prismix.dev/subscribe/openai — they can enter their email and subscribe to outage notifications directly. No account needed for basic email alerts.