---
title: "How to Build a Status Page for an AI API Service"
description: "Build a status page for an AI API service: how to split components, source data, define status levels, write incident updates, plus a pre-launch checklist."
url: https://cdnping.org/en/blog/build-status-page-for-ai-service
language: en
published: 2026-10-25
category: "Developer tools"
tags: ["status page","availability monitoring","AI API","incident management"]
source: cdnping.org
license: Free to quote and summarize with a link to the url above.
---
# How to Build a Status Page for an AI API Service

The hard part of building a status page is not choosing a tool. It is deciding four things up front: which components to list, who decides each component's status, what each level means, and what every incident update should say. For an AI API service, split components into "access gateway + model groups + console." Let automated probes and real-request statistics set the status, and leave people to confirm it and write the explanation. This article follows that order and ends with a pre-launch checklist.

As reference points, we use cdnping's own [API status page](/en/status) and [AGI Plan status page](/en/status/agiplan). AGI Plan is a commercial partner of cdnping, so we know both the approach and the shortcomings of these two pages well.

## What questions does a status page need to answer?

When users open a status page, they usually want to know three things:

1. Is the problem I'm seeing on your side?
2. If so, which part is affected, do you know about it, and roughly when will it be fixed?
3. Has your service been stable over the past while?

So a status page is not a monitoring dashboard. You don't need to put internal metrics such as CPU or queue length on it. Give conclusions that users can match against their own situation. For how users typically read status pages, see [How to read the OpenAI and Claude status pages](/en/blog/how-to-read-ai-status-pages).

## How should you split components so they help for an AI service?

The rule: a failure boundary that users can tell apart is a component boundary. Users can't distinguish an "auth service" from a "billing service," but they can tell "I can't log in to the console" from "the API returns 5xx."

A typical AI API service can be split like this:

| Component | What users see | Main data source |
|---|---|---|
| API access gateway | Can't connect, TLS failures, every request errors | External probes |
| Model groups (e.g. reasoning, general, lightweight) | One class of models errors or slows down more, others are fine | Real-request success rate |
| Console and login | Page won't load, can't log in, can't create keys | External probes + manual |
| Billing and quota | Odd charges, quota shown incorrectly | Manual |
| Docs and website | Page won't load | External probes |
| Upstream dependencies (display only, not counted in your own uptime) | An upstream vendor has an incident | Synced from the upstream's official status page |

The data shows why model groups need their own components. Take AGI Plan as an example. In cdnping's snapshot from October 17, 2026, probing the agiplan.dev entry point from a Cloudflare edge node (Denver) gave an availability field of 100% (collection had only started that day, so the window covered about an hour and a half). In the same snapshot, AGI Plan's publicly reported availability, computed from real requests over the last 1 day, was about 77.3% for the "fast group," 100% for the "balanced group," and about 99.8% for the "frontier model group." A reachable entry point does not mean every model group works. If a status page has only a single "API" component, it would stay green in this situation.

We suggest putting upstream dependencies in their own section, labeled "third party," and excluding them from your own uptime.

## Where does status data come from: automated probes, real requests, or manual posts?

Each of the three sources has blind spots, so no single one is enough.

| Source | What it can detect | What it can't detect | Best for driving |
|---|---|---|---|
| Scheduled external probes | Unreachable entry point, DNS/TLS problems, overall slowdown | Failures affecting only some models or some requests | Gateway, console, docs |
| Real-request statistics | Per-group success rate, error code distribution | Periods with no traffic (at night, with few requests, ratios are unreliable) | Model groups |
| Manual posts | Billing errors, data problems, planned maintenance | Slow to react, depends on on-call staff | Incident notes, maintenance notices |

For the difference between probes and real-request statistics, see [Synthetic monitoring vs. real user monitoring for AI](/en/blog/synthetic-monitoring-vs-real-user-monitoring-ai).

cdnping's /status uses the first two sources plus upstream sync. It probes each vendor's official API entry point from Cloudflare's edge every 5 minutes, syncs the official status pages of OpenAI, Anthropic, Kimi (Moonshot AI), Groq, Cloudflare, GitHub and Cursor every 15 minutes, and keeps 30 days of history. The exact definitions are written up in [our methodology](/en/methodology).

Probe data can inflate or shrink the real picture, so state your definitions clearly. For example: between 16:40 and 18:05 Beijing time on 2026-10-17, cdnping made 242 probes from the Denver (DEN) node. In that window, the availability field for the Kimi Open Platform was 94.4% with a p95 latency of 1125 ms, and every other entry point was at 100%. The window is only an hour and a half and comes from a single node, so the number says "failures were observed from this location during this period." It can't be used to judge long-term stability. When your status page shows your own numbers, label the window and the probe location in the same way.

For real-request statistics, watch the denominator. AGI Plan's public definition is "successes / (successes + failures caused by the platform itself)." Only 5xx counts as a platform failure; a user's 401 or 429 does not. You may disagree with that definition, but you must write it down. When only a few requests arrive per hour at night, one failure can drag the ratio down sharply. Set a minimum request count, and below it show "insufficient data" instead of red. For how to measure this yourself and settle on a definition, see [Measuring AI API uptime yourself](/en/blog/measure-ai-api-uptime-yourself).

### What does a minimal probe look like?

Suppose your API is at `https://api.example.com`. This command can go into any scheduled job and prints the status code, connect time and total time on each run:

```bash
curl -s -o /dev/null --max-time 10 \
  -w '%{http_code} %{time_connect} %{time_appconnect} %{time_total}\n' \
  https://api.example.com/v1/models
```

You can start with these rules: if no status code comes back (timeout, DNS failure, TLS failure), count it as a failure; 5xx counts as a failure; a 401 without a key means the gateway is working normally, so count it as a success. Use at least two probe locations in different regions, and call it an "entry point outage" only when both fail at the same time, so that one probe's network problem isn't blamed on you. For a fuller probing and alerting checklist, see [A guide to availability monitoring for AI apps](/en/blog/ai-app-availability-monitoring-guide).

## How should you define status levels?

Fewer levels are easier to use. We suggest four levels plus a maintenance state, with the thresholds written on the page:

| Level | Page label | Example threshold (5-minute window; adjust for your own case) |
|---|---|---|
| Operational | Operating normally | Success rate ≥ 99%, p95 latency within 2x baseline |
| Degraded performance | Some requests are slow | Success rate ≥ 99%, but p95 latency above 2x baseline |
| Partial outage | Some requests are failing | Success rate between 90% and 99%, or a model group is unavailable |
| Major outage | Most requests are failing | Success rate below 90%, or entry point unreachable |
| Under maintenance | Planned maintenance | A maintenance window announced in advance |

A few lessons:

- Let automation only raise the level. Returning to normal should need manual confirmation or several consecutive recovered windows, so the page doesn't flip between yellow and green.
- Vendors classify incidents very differently, so don't treat anyone else's distribution as a standard. In the official status pages that cdnping syncs, over the month from 2026-09-17 to 2026-10-17, OpenAI logged 4 major and 19 minor incidents, and Cloudflare logged 3 major and 19 minor. Most incidents are marked minor, and each vendor sets its own standard.
- Your availability target and level thresholds should line up. For how to compute targets and error budgets, see [SLI, SLO and SLA: what's the difference](/en/blog/sli-slo-sla-error-budget-explained).

## What should each incident update say?

Incident notices usually go through four stages: investigating, identified, monitoring, resolved. Each stage should answer a fixed set of questions:

| Stage | Must include | Avoid |
|---|---|---|
| Investigating | Symptoms, affected components, start time, time of next update | Causes that haven't been confirmed |
| Identified | The broad category of cause (upstream, config change, capacity) and what is being done | Wording that blames a specific vendor |
| Monitoring | Actions taken, whether metrics have recovered, whether users need to do anything | Conclusions like "fully fixed" that haven't been verified |
| Resolved | Impact period (start and end times with time zone), scope of impact, follow-up improvements | Empty apology paragraphs |

Write the title as "symptom + scope." Most titles on official status pages follow this structure. Here are a few that cdnping synced:

- Increased HTTP 502 Errors (Cloudflare, minor, lasted 591 minutes)
- Network Performance Issues in London (Cloudflare, major, lasted 13 minutes)
- Elevated Errors in China Network Colos (Cloudflare, minor)
- Widespread feature degradation (OpenAI, major, lasted 146 minutes)

The first three show the impact and location at a glance. The last has a broad scope, so you need to click in to see the components. A template:

```text
[Partial outage] Elevated request failure rate in the lightweight model group
Start time: 2026-10-16 14:05 (Beijing time)
Impact: About half of requests to the lightweight model group return 5xx. Other model groups and the console are normal.
Current progress: Identified as an elevated error rate at an upstream provider; traffic is being switched to a backup provider.
What users need to do: No configuration changes needed. If you have retry logic, we recommend exponential backoff.
Next update: within 30 minutes.
```

The times and ratios in the template are examples. AGI Plan's public data does show hours that look like this. In the snapshot cdnping mirrored, starting at 14:00 Beijing time on October 16, two consecutive hourly buckets had 722 and 877 failed requests, more than the successes in the same hours (664 and 455). For hours like these, the status page should have a matching incident record. Otherwise users will feel the page doesn't reflect reality.

Two more rules: put a "next update" time in every update, and if nothing has changed by then, post a "still working on it" update anyway. Don't rewrite earlier updates of a resolved incident; keep the original text and add clarifications.

## How long should history be kept, and should you offer RSS and JSON?

Keep history for at least 30 days, enough to cover the most common question, "has it been stable over the last month?" Keep longer if you can. cdnping's /status currently keeps 30 days, and because collection only began on 2026-10-17, the history is still short, which the page says plainly.

We suggest offering machine-readable outputs:

- JSON: for users' monitoring systems and bots. cdnping's open data endpoint `/api/status` is published under CC BY 4.0. AGI Plan provides hourly success and failure counts per capability group at `https://agiplan.dev/api/status/requests?month=YYYY-MM`, with no login required.
- RSS / Atom: for people who only want to subscribe to incident notices, with one entry per incident update.
- Webhook or email subscriptions: add these once your user base grows.

For JSON fields, you can use a structure like this (an example, not the definition of any existing API):

```json
{
  "updated": "2026-10-23T12:00:00Z",
  "components": [
    {"id": "gateway", "status": "operational", "uptime_30d": 0.999},
    {"id": "group-fast", "status": "partial_outage", "uptime_30d": 0.98}
  ],
  "incidents": [
    {"id": "inc-001", "title": "Elevated request failure rate in the lightweight model group",
     "impact": "minor", "started": "2026-10-16T06:05:00Z", "resolved": null}
  ]
}
```

Once a field is public, avoid renaming it. Someone downstream will have hard-coded the parsing.

## What should you build it with, and do you need a server?

There are many open source and hosted options. We don't rank them here, only group them into three types by deployment style. Which to pick depends on what you're willing to maintain:

| Type | Approach | Good for | Watch out for |
|---|---|---|---|
| Serverless | Run probes from CI scheduled jobs or edge cron jobs, write results to a repo or object storage, generate a static page | Small teams, few components | Probe frequency is limited by the scheduler, and there is only one probe location |
| Self-hosted app | Long-running service + database, with its own admin panel and incident editor | Manual posts, subscription notifications | Deploy the status page separately from the main service, or it goes down with it |
| Hosted service | A third party hosts the page and subscriptions | You don't want to maintain anything | Data definitions are limited by the platform, and you must push your own request statistics in |

Whichever type you choose, insist on one thing: the status page and the monitored service must not share the same infrastructure, including DNS, CDN and database. If your main site is on Cloudflare, host the status page elsewhere, and vice versa. In mid-October 2026, Cloudflare's own status page logged failures in Workers Cron Triggers and Durable Objects. A probe running on those components could have had gaps in its data during those days.

## Pre-launch checklist

- [ ] Components are split along failure boundaries users can tell apart, with model groups listed separately
- [ ] Each component states its data source: probes, request statistics or manual
- [ ] Probes run from at least two regions, and a single-point failure doesn't turn the page red directly
- [ ] Request statistics have a minimum request count, and show "insufficient data" when the sample is too small
- [ ] Level thresholds and availability definitions are written on the page or in a methodology note
- [ ] The incident template includes symptoms, scope, start time (with time zone), what users need to do, and next update time
- [ ] Upstream dependencies are in their own section and not counted in your own uptime
- [ ] History covers at least 30 days and states the collection start date
- [ ] JSON and RSS are provided, with field names documented
- [ ] DNS, CDN and database are separate from the main service
- [ ] Run one drill: cause a component failure by hand and see how long the page takes to change color and the notice takes to go out

The last item is the easiest to skip and the best at exposing problems. After launch, you can compare your status page against a page like [/down](/en/down), which combines official status, API probes and user reports, to see whether the two agree. To see what the official status pages actually logged over a past period, read [AI service incidents in September–October 2026](/en/blog/ai-service-incidents-sep-oct-2026).
