/ docs / badges

Add an uptime badge to a GitHub README

Add a live uptime or status badge for a Fettle monitor to a GitHub README: turn it on, copy the Markdown or HTML, and know what the badge makes public.

Updated

What the two badges show

Each monitor has two badges, both SVG images served from the API host. Put either in a README and it shows the monitor’s live state to anyone reading it:

  • uptime.svg reads uptime 30d next to a percentage, truncated down to two decimals so it never rounds up to 100%. It is computed the same way as the dashboard’s uptime: confirmed downtime against the time the monitor was watched. The badge truncates where the dashboard rounds, so the two can differ by 0.01. Green from 99.5%, yellow from 98%, red below that, and grey no data before the first checks are in. For a monitor younger than the window, the label names its age instead, such as uptime 3d.
  • status.svg reads status next to the current state: up in green, degraded in yellow, down in red, paused or pending in grey.

Two query parameters shape a badge:

ParameterValuesEffect
period7d, 30d (default), 90dThe uptime window. The status badge ignores it.
styleflat (default), flat-squareRounded or square corners, on both badges.

A value the badge does not know falls back to the default instead of breaking the image. The label text and colours are fixed. The uptime window cannot reach further back than the organization’s plan keeps history, in days: 7 on Free, 90 on Plus, 180 on Pro and 365 on Max. On a plan that keeps 7 days, a period=30d badge reads uptime 7d. What else each plan includes is on the pricing page.

Turn the badge on

Badges are on every plan and start switched off. In the dashboard, open the monitor under Monitors and flip the Public badge switch. The card then shows both badges with their Markdown, HTML and image URL ready to copy, and lets you pick the period and style; it offers only the periods your plan’s history covers.

With the uptime monitoring API, send badge_enabled in a PATCH /v1/monitors/{id} with a write-scoped API key. The field is not part of the create body, so a new monitor gets its badge in a second call:

Turn the badge on
curl -s -X PATCH https://api.fettle.sh/v1/monitors/YOUR_MONITOR_ID \
  -H "Authorization: Bearer fettle_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"badge_enabled": true}'

An agent connected through the Fettle MCP server does the same with the update_monitor tool and its badge_enabled argument.

A monitor that is a component of a published status page already has a working badge, with the switch on or off: its state is public on that page anyway.

Add it to a GitHub README

Replace YOUR_MONITOR_ID with the monitor’s id. It is the last segment of the monitor’s address in the dashboard, the id field in GET /v1/monitors, or what the MCP list_monitors tool returns. The link around the image can point anywhere; a status page is the natural target.

Uptime and status badges (Markdown)
[![Uptime](https://api.fettle.sh/public/badges/YOUR_MONITOR_ID/uptime.svg?period=30d)](https://status.fettle.sh/your-page)
[![Status](https://api.fettle.sh/public/badges/YOUR_MONITOR_ID/status.svg)](https://status.fettle.sh/your-page)

The same two badges as HTML, for a docs site or any page that takes markup:

Uptime and status badges (HTML)
<a href="https://status.fettle.sh/your-page"><img src="https://api.fettle.sh/public/badges/YOUR_MONITOR_ID/uptime.svg?period=30d" alt="Uptime"></a>
<a href="https://status.fettle.sh/your-page"><img src="https://api.fettle.sh/public/badges/YOUR_MONITOR_ID/status.svg" alt="Status"></a>

How fresh the badge is

A rendered badge is cached for five minutes and sent with Cache-Control: public, max-age=300 and an ETag, so a README shows a state at most about ten minutes old: up to five in Fettle’s cache and up to five more in the browser or proxy that fetched it. GitHub fetches README images through its Camo image proxy, which keeps its own copy; curl -X PURGE on the image’s Camo URL forces a refresh, as GitHub’s page describes.

A badge you may not see, because the id does not exist, the badge is off or its status page is unpublished, answers 404 with the same grey unknown image in every case, cached for 60 seconds. If the README was loaded just before you turned the badge on, that grey image can stay for up to about two minutes. Requests are limited to 300 a minute per client address for each badge type; behind GitHub, that client is Camo, not the reader.

What does a badge make public?

Anyone with the badge URL sees the monitor’s current state, its uptime percentage and the window in its label, which can reveal the monitor’s age. Nothing else: no monitor name, no target URL, no regions, no response times, no incident details. The monitor id in the URL opens nothing else on its own.

Every Fettle route other than the badges needs an API key or a signed-in session. A public repository makes the URL public, so treat the state of a badged monitor as public information.

Turn it off

Flip the switch off, or send {"badge_enabled": false} in the same PATCH. New requests get the grey unknown image once the cached copies expire, within about ten minutes, plus whatever GitHub’s proxy holds. If the monitor is on a published status page, the badge keeps working until you remove it from the page or unpublish the page. Deleting the monitor turns its badges off too.