← Back to Documentation

REST API Reference

PF-SUMP-001 product endpoints  |  v1.1  |  Updated: 2026-02-27

All paths are relative to http://<device-ip>/api/v1. LAN-only. No authentication.


GET /sump/status

Returns the full current state of the sump pump monitor — run state, active alerts, protection mode, lockout info, learning progress, and cumulative stats.

Response 200 OK

{
  "pump_running": false,
  "current_run_s": 0,
  "current_power_w": 0.0,
  "alerts": [],
  "protection_mode": "active",
  "protection_auto_disabled": false,
  "lockout_active": false,
  "lockout_remaining_s": 0,
  "lockout_retries_used": 0,
  "lockout_alert": null,
  "run_count_total": 87,
  "runs_last_24h": 7,
  "total_runtime_s": 2958,
  "last_outage_s": 0,
  "last_run_end_ms": 1708300000000,
  "last_run_dur_s": 34,
  "last_run_avg_w": 762.4,
  "last_run_peak_w": 812.0,
  "idle_w": 0.0,
  "active_w": 780.0,
  "on_threshold_w": 234.0,
  "inter_run_gap_mean": 21600.0,
  "alert_enable_mask": 7,
  "relay_cut_mask": 1,
  "inactivity_alert_min": 7200,
  "anomaly_lockout_min": 10,
  "lockout_max_retries": 3,
  "rhythm_hex": "000000010001000200010000...",
  "rhythm_head": 142,
  "rhythm_last_bin_ms": 1708300200000
}

Fields

FieldTypeDescription
pump_runningbooleantrue if pump is currently detected as ON
current_run_sintegerSeconds into current run (0 if idle)
current_power_wfloatInstantaneous power reading (watts)
alertsstring[]Currently active alert keys, e.g. ["power_anomaly_low", "long_run"]. Empty if none.
protection_modestringCurrent protection mode: learning, active, or suspended
protection_auto_disabledbooleantrue if any relay-cut flag was system-disabled due to exhausted retries
lockout_activebooleantrue if relay is currently held OPEN during a lockout period
lockout_remaining_sintegerSeconds remaining in current lockout (0 if not in lockout)
lockout_retries_usedintegerHow many relay trips have occurred for the current alert type
lockout_alertstring | nullAlert key that triggered the current lockout, or null
last_run_end_msinteger | nullEpoch ms of last completed run, or null if no runs since boot
last_run_dur_sintegerDuration of last completed run in seconds
last_run_avg_wfloatAverage power during last completed run
last_run_peak_wfloatPeak power during last completed run
last_outage_sintegerDuration of last detected power outage in seconds (0 if none)
run_count_totalintegerCumulative lifetime run count (persisted in NVS)
runs_last_24hintegerPrecise pump run count in the rolling 24h window
total_runtime_sintegerCumulative lifetime runtime in seconds
idle_wfloatLearned idle power in watts
active_wfloatLearned active power in watts
on_threshold_wfloatCurrent ON detection threshold in watts
inter_run_gap_meanfloat | nullMean seconds between consecutive pump runs. null if fewer than 2 runs.
alert_enable_maskintegerCurrent alert-enable bitmap (0–31). Default 7.
relay_cut_maskintegerCurrent relay-cut bitmap (0–7).
inactivity_alert_minintegerMinutes without a cycle before Expected Run alert fires. Default 7200.
anomaly_lockout_minintegerMinutes relay stays OPEN after anomaly. Default 10.
lockout_max_retriesintegerAuto-release attempts before protection disables. Default 3.
rhythm_hexstring288-char hex string — rolling 24h activity bins
rhythm_headintegerIndex (0–287) of the current bin
rhythm_last_bin_msintegerEpoch ms when the current head bin was last advanced

Protection mode values

ModeDescription
learningInsufficient baseline data — only power outage fires
activeWattage and runtime baselines met — all alerts enabled
suspendedWas active, inactivity alert fired — reverts to learning until next cycle

Alert key values

KeyDisplay nameDescription
power_anomaly_lowLow PowerPossible dry run
power_anomaly_highHigh PowerPossible blockage
long_runExcessive RunRun exceeds 2× learned mean duration
frequent_cyclingShort CyclingCycles in rolling 60-min window exceed 2× mean hourly rate
inactivityExpected RunNo pump cycle for inactivity_alert_min minutes

GET /sump/last-run

Returns detailed stats and power waveform for the last completed pump cycle.

Response 200 OK

{
  "start_ms": 1708299965000,
  "end_ms": 1708300000000,
  "dur_s": 34,
  "avg_w": 762.4,
  "peak_w": 812.0,
  "std_w": 18.7,
  "sample_count": 34,
  "samples": [210.5, 810.2, 795.0, 780.1, 770.3, 762.8, ...]
}

Fields

FieldTypeDescription
start_msinteger | nullEpoch ms when pump turned ON
end_msinteger | nullEpoch ms when pump turned OFF
dur_sintegerCycle duration in seconds
avg_wfloatMean power during cycle
peak_wfloatPeak power observed
std_wfloatStandard deviation of power
sample_countintegerNumber of valid entries in samples[] (0–60)
samplesfloat[]Power readings at ~1 Hz (first 60 seconds of run)

samples[] captures the first 60 seconds. For shorter runs, this is the complete waveform. Data is NVS-persisted — survives reboot, overwritten by the next completed cycle.


GET /sump/config

Returns all current configuration parameters.

Response 200 OK

{
  "inactivity_alert_min": 7200,
  "anomaly_lockout_min": 10,
  "lockout_max_retries": 3,
  "alert_enable_mask": 7,
  "relay_cut_mask": 1
}

Fields

FieldTypeDefaultRangeDescription
inactivity_alert_mininteger72001–43200Minutes without a cycle before Expected Run alert. 7200 = 5 days.
anomaly_lockout_mininteger101–480Minutes relay stays OPEN after anomaly.
lockout_max_retriesinteger31–10Auto-release attempts before protection permanently disables.
alert_enable_maskinteger70–31Bitmap. Bit 0=low power, 1=high power, 2=long run, 3=freq cycling, 4=inactivity.
relay_cut_maskinteger10–7Bitmap. Only bits 0–2 meaningful (low power, high power, long run).

POST /sump/config

Update configuration. Accepts a partial JSON body — only fields present are changed. Persisted to NVS immediately.

Request examples

// Change lockout timing
{ "anomaly_lockout_min": 15, "lockout_max_retries": 5 }

// Enable high-power relay cut (bits 0+1)
{ "relay_cut_mask": 3 }

// Enable frequent cycling alert (bits 0–3)
{ "alert_enable_mask": 15 }

// Set inactivity alert to 3 days
{ "inactivity_alert_min": 4320 }

Validation rules

FieldRule
inactivity_alert_minInteger, 1–43200
anomaly_lockout_minInteger, 1–480
lockout_max_retriesInteger, 1–10
alert_enable_maskInteger, 0–31
relay_cut_maskInteger, 0–7

Response 200 OK

Full config object (same as GET).

Error responses

StatusBodyCondition
400"Empty body"No request body
400"Invalid JSON"Body is not valid JSON
400"<field> must be <min>–<max>"Numeric field out of range
400"<field> must be a number"Non-numeric value

GET /sump/history

Returns the alert event ring buffer — up to 32 most recent events, ordered oldest first.

Response 200 OK

[
  {
    "event": "alert_fired",
    "alert": "power_anomaly_low",
    "timestamp_ms": 1738886400000,
    "run_dur_s": 12,
    "power_w": 520.0,
    "relay_cut": true
  },
  {
    "event": "alert_cleared",
    "alert": "power_anomaly_low",
    "timestamp_ms": 1738886420000,
    "duration_s": 20
  },
  {
    "event": "power_outage",
    "timestamp_ms": 1738800000000,
    "outage_s": 3600
  },
  {
    "event": "mode_change",
    "timestamp_ms": 1739145600000,
    "from": "learning",
    "to": "active"
  },
  {
    "event": "device_boot",
    "timestamp_ms": 1739318400000,
    "reason": "power_on"
  }
]

Event types

EventDescriptionExtra fields
alert_firedActive alert addedalert, relay_cut, power_w, run_dur_s
alert_clearedActive alert removedalert, duration_s
power_outageBoot gap > 2 min detectedoutage_s
protection_auto_disabledMax retries exhaustedalert
mode_changeProtection mode transitionfrom, to
lockout_resetUser reset lockout
device_bootDevice bootedreason

Normal pump runs do NOT appear in this ring. Pump activity is captured by the rhythm ring in /sump/status.


POST /sump/lockout/reset

Clear any active lockout, re-enable any system-disabled protection flags, and reset the retry counter.

Response 200 OK

{ "status": "lockout_reset" }

What gets reset

StateReset to
lockout_activefalse — relay closes immediately
lockout_retries_used0
protection_auto_disabledfalse
System-disabled cut flagsRestored to true in NVS

POST /sump/stats/reset

Reset all cumulative statistics, clear alert history, clear rhythm ring, and reset all learned baselines. Device re-enters learning mode.

Response 200 OK

{ "status": "stats_reset" }

What gets reset

DataReset to
Run count, runtime0
Welford trackers (4×)Zeroed
Bimodal EMA (idle_w, active_w)0.0
Rhythm ring (288 bins)All zeros
Alert history ring (32 slots)Empty
Protection modelearning
Lockout stateCleared

GET /sump/learn

Returns learning / baseline convergence data: Welford CV values, per-metric readiness flags, inter-run gap stats, and the bimodal power baselines.

Response 200 OK

{
  "mode": "learning",
  "cycle_count": 9,
  "wattage_mean": 762.4,
  "wattage_cv": 8.2,
  "wattage_ready": true,
  "runtime_mean": 34.0,
  "runtime_cv": 46.1,
  "runtime_ready": false,
  "cycle_rate_mean": 7.2,
  "cycle_rate_cv": 45.0,
  "cycle_rate_ready": false,
  "inter_run_gap_mean": 420.0,
  "inter_run_gap_cv": 32.5,
  "inter_run_gap_ready": true,
  "idle_w": 0.0,
  "active_w": 780.0
}

Fields

FieldTypeDescription
modestringProtection mode: learning, active, suspended
cycle_countintegerTotal valid pump cycles observed
wattage_meanfloatWelford mean peak power per cycle (W)
wattage_cvfloatWattage CV (%). Threshold: < 15%
wattage_readybooleantrue if below threshold
runtime_meanfloatMean run duration (seconds)
runtime_cvfloatRuntime CV (%). Threshold: < 40%
runtime_readybooleantrue if below threshold
cycle_rate_meanfloatMean cycles per hour
cycle_rate_cvfloatCycle rate CV (%)
cycle_rate_readybooleanAlways true (informational)
inter_run_gap_meanfloatMean gap between runs (seconds)
inter_run_gap_cvfloatInter-run gap CV (%)
inter_run_gap_readybooleantrue if ≥ 2 runs observed
idle_wfloatLearned idle power baseline (W)
active_wfloatLearned active power baseline (W)

Readiness thresholds

MetricCV thresholdRequired for ACTIVE
Wattage< 15%Yes
Runtime< 40%Yes
Cycle rateNo (informational)
Inter-run gapNo (informational)

Transitions learningactive when both wattage_ready and runtime_ready are true and ≥ 5 cycles recorded.


Common Notes