FastAPI-Cronsv2.4.0

Install

The dashboard ships with the package. There is nothing extra to install:

bash
pip install fastapi-crons

pip install fastapi-crons[dashboard] still works

Earlier versions documented a dashboard extra. It is kept as an empty extra so existing install commands and lockfiles keep working — it simply installs nothing beyond the base package.

Serving it

The dashboard is a route on the cron router. Mount the router and it is available at /dashboard underneath whatever prefix you chose.

pythonapp.py
from fastapi import FastAPI
from fastapi_crons import Crons, get_cron_router

app = FastAPI()
crons = Crons(app)

app.include_router(get_cron_router(), prefix="/api")


@crons.cron("*/5 * * * *", name="print_hello")
def print_hello():
    print("Hello! I run every 5 minutes.")

With the router mounted at /api, open:

bash
http://127.0.0.1:8000/api/dashboard

What it shows

The UI reads the same JSON the management endpoints expose, so it reflects whatever the API reports:

PanelShows
JobsEvery registered job, its cron expression and tags.
ScheduleLast run and next run times.
StatusCurrent status and the outcome of the most recent run.
HealthThe result of the health endpoint.

If the bundle is missing

Only possible if the package was built without its data files. The route answers 500 with a reinstall hint rather than an opaque traceback, and every other endpoint keeps working:

json
{
  "detail": "The fastapi-crons dashboard bundle is missing from this installation.\nReinstall with: pip install --force-reinstall fastapi-crons"
}

Securing it

The dashboard has no authentication of its own

It exposes job names, schedules and run history, and sits alongside the endpoint that can trigger a job on demand. Anyone who can reach the route can read all of it. Put it behind your own auth or keep it off the public internet.

The simplest approach is a router-level dependency, which covers the dashboard and the management endpoints together:

python
from fastapi import Depends, FastAPI, HTTPException, status
from fastapi.security import HTTPBasic, HTTPBasicCredentials

security = HTTPBasic()


def require_admin(credentials: HTTPBasicCredentials = Depends(security)):
    if not is_valid_admin(credentials):
        raise HTTPException(status.HTTP_401_UNAUTHORIZED)


# Everything under /api now requires authentication.
app.include_router(
    get_cron_router(),
    prefix="/api",
    dependencies=[Depends(require_admin)],
)

Alternatively, mount the router on an internal-only port, or restrict the path at your reverse proxy.

Size

The bundle is roughly 850 KB on disk, which compresses to about 270 KB in the wheel. That is the whole cost of having it built in, and it is why the dashboard is not gated behind an extra: a second distribution would have bought very little and cost a separate release train.

Esc
IntroductionGetting StartedInstallationGetting StartedQuick StartGetting StartedCron ExpressionsCore ConceptsDefining JobsCore ConceptsHooksCore ConceptsConfigurationCore ConceptsState BackendsBackendsDistributed LockingBackendsDashboardOperationsHTTP EndpointsOperationsCLIOperations