Skip to content

Latest commit

 

History

History
228 lines (167 loc) · 5.71 KB

File metadata and controls

228 lines (167 loc) · 5.71 KB

Ofelia API Documentation

Overview

Ofelia serves a JSON API when the web server is enabled (--enable-web, default address :8081). Every API route lives under the /api/ prefix; the health endpoints live at the server root. This document describes the endpoints that exist in the code (web/server.go — the routes table is the source of truth); if you find a mismatch, that is a bug in this file.

Two general rules:

  • All mutating endpoints are POST and take a JSON body. Any other method returns 405 Method Not Allowed.
  • A malformed JSON body returns 400 Bad Request; an unknown job name returns 404 Not Found; internal failures return 500 Internal Server Error with a short plain-text message.

Authentication

Authentication is optional and disabled unless the daemon is configured with web auth. When disabled, the auth endpoints below are not registered and every other endpoint is open.

When enabled, all /api/ routes except /api/login, /api/auth/status and /api/csrf-token require authentication via either:

  • the auth_token cookie set by login (HttpOnly, SameSite=Strict; Secure when the request arrived over TLS or with X-Forwarded-Proto: https), or
  • an Authorization: Bearer <token> header carrying the token returned by login.

Login

POST /api/login
Content-Type: application/json

{"username": "admin", "password": "secret"}

Response 200 OK (and the auth_token cookie):

{"token": "<token>", "csrf_token": "<csrf-token>", "expires_in": 86400}

Failed credentials return 401 Unauthorized; repeated failures are rate limited per client IP. There is no refresh endpoint — log in again when the token expires.

Logout

POST /api/logout

Clears the auth cookie. Returns 204 No Content.

Auth status

GET /api/auth/status

Reports whether authentication is enabled and whether the caller is authenticated.

CSRF token

GET /api/csrf-token

Returns the CSRF token for the session; the web UI sends it with the login form.

Jobs

List jobs

GET /api/jobs            # active jobs
GET /api/jobs/removed    # jobs removed from the configuration
GET /api/jobs/disabled   # disabled (paused) jobs

Each returns a JSON array of job objects:

[
  {
    "name": "backup",
    "type": "run",
    "schedule": "@daily",
    "command": "backup.sh",
    "running": false,
    "lastRun": {
      "date": "2026-08-26T00:00:00Z",
      "duration": 300000000000,
      "failed": false,
      "skipped": false,
      "stdout": "",
      "stderr": ""
    },
    "nextRuns": ["2026-08-27T00:00:00Z"],
    "prevRuns": ["2026-08-26T00:00:00Z"],
    "origin": "ini",
    "config": {"…": "full job configuration as JSON"}
  }
]

lastRun is omitted when the job has never run. duration values are Go time.Duration nanoseconds. origin is one of ini, label, api, web.

Job history

GET /api/jobs/{name}/history

Returns a JSON array of executions in the shape of lastRun above (plus an error string when the execution errored). 404 Not Found for unknown jobs or job types without history.

Run a job now

POST /api/jobs/run
Content-Type: application/json

{"name": "backup"}

Returns 204 No Content on success.

Disable / enable a job

POST /api/jobs/disable
POST /api/jobs/enable
Content-Type: application/json

{"name": "backup"}

Returns 204 No Content. Works for jobs of every origin — disabling an INI/label job from the API is the supported way to suppress it temporarily, and the disabled state is persisted across restarts.

Create a job

POST /api/jobs/create
Content-Type: application/json

{
  "name": "cleanup",
  "type": "run",
  "schedule": "0 2 * * *",
  "image": "alpine:latest",
  "command": "cleanup.sh"
}

The request body (jobRequest) accepts:

Field Type Notes
name string required; ≤256 chars, no control characters
type string run, exec, local, service-run, compose
schedule string cron expression or @shortcut
command string
image string run jobs
container string exec jobs
file string compose jobs
service string service-run jobs
exec bool compose jobs: exec in a running service

Returns 201 Created. Validation failures return 400 Bad Request. API-created jobs are persisted and survive restarts.

Update a job

POST /api/jobs/update
Content-Type: application/json

Same body as create. Full replace: omitted optional fields reset to their defaults. Returns 200 OK when an existing job was updated, 201 Created when the job did not exist and was created.

Delete a job

POST /api/jobs/delete
Content-Type: application/json

{"name": "cleanup"}

Returns 204 No Content. Jobs owned by the INI file or Docker labels return 403 Forbidden — edit the owning configuration to remove them (or use /api/jobs/disable to suppress them); only API/web-created jobs can be deleted here.

Configuration

GET /api/config

Returns the running daemon configuration as JSON, with the job collections stripped (use the job endpoints for those).

Health

Registered at the server root (not under /api/, no authentication):

GET /health    # aggregate health report
GET /healthz   # alias of /health
GET /ready     # readiness probe
GET /live      # liveness probe

Errors

Errors are plain-text messages with the appropriate status code: 400 invalid body or validation failure, 401 unauthenticated (auth enabled), 403 config-owned job on delete, 404 unknown job, 405 wrong method, 500 internal failure. Login attempts are rate limited per client IP.