Table of Contents

Everything you need to integrate your API with Still200 — an uptime monitoring platform for developers. Still200 monitors your API by polling a health endpoint that you define and expose. Choose the setup that fits your needs:

  Simple Setup Full Setup
Time to integrate ~2 minutes ~15 minutes
What’s monitored API reachability API + individual dependencies
Alert detail Up/down Per-dependency root cause analysis
Best for Getting started fast Production services

Backend Setup

Simple Setup

The fastest way to set up monitoring. Add a single route that returns your service name, register it in the app, and you’re done.

from fastapi import FastAPI
 
app = FastAPI()
 
@app.get("/health")
async def health():
    return {"service_name": "my-api"}

That’s it. No dependencies, no extra packages. Make sure your endpoint returns a 200 status code — Still200 reads health from the response body, but won’t parse it if the request fails.

Full Setup

Follow the Health Check Spec below to format your response correctly.

Validate your endpoint

Before registering your health check URL, confirm the format is correct:

curl -X POST -H "Content-Type: application/json" \
    -d '{"url": "https://myapi.com/health"}' \
    https://api.still200.com/monitors/validate

A passing response looks like this for the simple setup:

{
  "service_name": "my-api",
  "status": "healthy",
  "status_code": 200,
  "checks": {},
  "error": null
}

and it looks like this for the full set up:

{
  "service_name": "My API",
  "status": "healthy",
  "status_code": 200,
  "checks": {
    "database": {
      "status": "healthy",
      "latency_ms": 74.33
    },
    "redis": {
      "status": "healthy",
      "latency_ms": 5.71
    }
  },
  "error": null
}

If your format is wrong, the response will include an error string describing what to fix:

{
  "service_name": "",
  "status": "unknown",
  "status_code": 200,
  "checks": {},
  "error": "Invalid response format. Check that your response conforms to the expected response."
}

Once validated, you can register your monitor in the app.

Register Your Monitor

1. Download Still200 from the Apple App Store

2. Add your monitor. Paste your health check URL into the app and set your preferred check interval.

3. You’re live. Still200 will begin polling your endpoint immediately. If a check fails, you’ll receive a push notification on your phone. More alert channels coming soon.


Health Check Spec

Still200 monitors the individual dependencies inside your service, not just whether the HTTP response is 200. To support this, your health endpoint must return a JSON body in the format described below.

Endpoint Requirements

  • Method: GET
  • Content-Type: application/json
  • Status Code: Return 200 regardless of internal health status. Still200 reads health from the response body, not the HTTP status code.

Fields

Field Type Required Description
service_name string Yes Human-readable name shown in the app and alert notifications.
checks object No Map of dependency names to their status. An empty object {} is valid.
checks[n].status string Yes One of healthy, degraded, or unhealthy. See Status Values below.
checks[n].latency_ms float No Time in milliseconds to connect to or query the dependency.
checks[n].error string No Error detail surfaced in alerts and RCA when status is not healthy.

Status Values

Value Meaning Still200 behaviour
healthy Dependency is reachable and performing normally. No action.
degraded Reachable but slow or returning soft errors. Triggers an alert after the consecutive failure threshold is met.
unhealthy Dependency is down or unreachable. Triggers an alert after the consecutive failure threshold is met.

Code Samples

Python (FastAPI)

import asyncio
from fastapi import FastAPI, Depends
from pydantic import BaseModel
from typing import Dict, Literal, Optional

app = FastAPI()

class CheckResult(BaseModel):
    status: Literal["healthy", "degraded", "unhealthy"]
    latency_ms: float
    error: Optional[str] = None

class HealthCheckResponse(BaseModel):
    service_name: str
    checks: Dict[str, CheckResult] = {}

@app.get("/health", response_model=HealthCheckResponse)
async def health(
    db = Depends(get_db),
    redis_client = Depends(get_redis)
) -> HealthCheckResponse:
    # Execute dependency checks concurrently
    async with asyncio.TaskGroup() as tg:
        db_check = tg.create_task(check_db(db=db))
        redis_check = tg.create_task(check_redis(redis_client=redis_client))

    checks = {
        "database": db_check.result(), 
        "redis": redis_check.result()
    }
    
    return HealthCheckResponse(
        service_name="My API",
        checks=checks,
    )

Contributing

Found a bug in the examples or want to add a sample in another language? Pull Requests are welcome.

Failure Semantics

Consecutive failure threshold. Still200 does not alert on the first failed check. An alert is sent once your endpoint has failed on a set number of consecutive checks. This prevents transient blips from waking you up at 3am.

Timeout. If your endpoint does not respond within the check timeout, Still200 treats it as a failed check. Keep your health handler fast — aim for under 500ms. Running dependency checks concurrently (as shown in the samples above) helps significantly.

HTTP status codes. Still200 reads health from the response body. Return 200 from your endpoint even when internal dependencies are unhealthy — Still200 inspects the status fields inside checks to determine alert eligibility.

Partial failures. A single unhealthy check in an otherwise healthy response will trigger the failure path after the threshold is met.

FAQs

Does my health endpoint need to be publicly accessible?

Yes. Still200 polls your endpoint from its own infrastructure, so it must be reachable over the public internet.

Can I add custom checks beyond databases and caches?

Yes. The checks map accepts any string key. Common additions include external API dependencies (stripe, sendgrid). Name them whatever is meaningful in your context.