Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Actions Reference

There is no separate HTTP/REST API for the UI; see Reactive Loop for how the pieces fit. Every server-side operation is one of these named actions. All of them are TAB scoped, and the URL is <basePath>_action/<name>, the same in every tab: the via_ctx field of the JSON body tells the server which tab a request belongs to. Templates always resolve the URL with {{ actionName.url() }} so the base path is right (the Twig name is the camelCase of the action name, set-range becomes setRange). A script scrapes via_ctx and the signal ids from the page (see Environment Notes).

Inputs are either signals, posted as the JSON body the way Datastar sends them, or query parameters on the action URL (?id=), read with $c->input().

Every action POST needs an Origin header naming the host of the request, as a browser sends it. Outside dev mode (NFSEN_DEV_MODE) php-via answers a POST without one with 403 Forbidden: missing Origin, and one whose Origin names another host than the request’s Host header with 403 Forbidden: untrusted origin, so a reverse proxy has to pass the original Host on.

Shell and controls

ActionFileInputDoes
navigateShellActions.phpsignal pageRenders the page the client switched to; an unknown page is reset to the default page
dismiss-notificationShellActions.php?page=<page id>&id=<notice id>Removes a notice from that page’s state; without a known page, from every page
kill-nfdumpUtilityActions.phpnoneSends SIGTERM to every nfdump this tab’s query runs (a split query and a filtered graph run several), by query handle (see NfdumpSlots), and names their PIDs; the notice goes to the page that owns query_kind
ip-infoUtilityActions.php?ip=Renders the IP info dialog into the modal root: reverse DNS, then GeoIP or the web service (public) or Netbox (private)
set-rangeRangeActions.php?op=preset&v=1h|24h|7d|30d|1y, ?op=duration&n=6&u=h|d|w, ?op=abs&from=&to= (epoch seconds), ?op=back, ?op=forward, ?op=now, ?op=zoomout, ?op=pinMoves the global window. Presets, durations and now make it live; back, pin and an absolute window that ends in the past pin it. back is refused at the start of the stored data. Reads no capture file
apply-globalsRangeActions.phpsignals graph_sources, protocol, graph_trafficUnitNormalises the global sources, protocol and unit, then re-renders
change-profileRangeActions.phpsignal selected_profileSwitches the nfdump profile, moves the window to the end of its data, saves the choice to preferences.json
refresh-graphsGraphActions.phpthe graph_* signalsRe-renders the traffic graph for the current options (the live tick)
validate-filterQueryKitActions.php?target=overview|talkers|flows|conversations|drawer|alertChecks the target’s filter with nfdump -Z and writes the answer into _flt_<target>; the newest request wins, and a check that cannot run answers Filter could not be checked
estimate-queryQueryKitActions.php?target=overview|overview-topn|talkers|flows|conversations|drawerWrites _est_<target>: first pending, then files, bytes, seconds, runs, clamp and whether the rate was measured (Estimate::toArray())

Overview

ActionFileInputDoes
overview-topnOverviewPage.phpsignals ov_tab, ov_dir, ov_limit, ov_order, and the globalsComputes the KPI cards and the top-N table from the SQLite lists in a coroutine; a second request for the same inputs while one runs is dropped
overview-topn-runOverviewPage.phpthe sameThe exact run with nfdump for a window outside retention (query kind overview-topn), split into parallel time slices when the read is large
run-filtered-graphGraphActions.phpsignal graph_filter and the graph optionsBuilds the filtered series behind Apply filter, one nfdump per bin, one bin per free nfdump process (query kind graph)

Top Talkers

ActionFileInputDoes
stats-actionsStatsActions.phpthe stats_* signals (stats_for, stats_dir, stats_count, stats_orderBy, filter, byte limits, aggregation)Runs the statistic (query kind stats), split into parallel time slices when the read is large, and stores the result for that statistic
talkers-selectStatsActions.phpsignal stats_forRe-renders only, so a statistic with a stored result shows it; runs nothing
talkers-panelStatsActions.php?panel=proto|asRuns a side panel: -o csv -n 10 -s proto/bytes or -s as/bytes with the query card’s filter (query kind talkers-panel)

Flows

ActionFileInputDoes
flow-actionsFlowActions.phpthe flows_* signalsRuns the listing (query kind flows) and stores the result
flows-windowFlowWindowActions.php?result=<id>&offset=<n>&count=<n>, body only via_ctxPatches the list with rows offset to offset + count (at most 500) in the tab’s order and columns
flows-sortFlowWindowActions.php?result=<id>&key=<column>&dir=asc|desc, body only via_ctxSorts the list, stable, empty values last, and answers from the top
flows-columnsFlowWindowActions.php?result=<id>&hidden=<keys>, body only via_ctxHides the named columns (the whole set) and answers with the window the list holds
flows-exportFlowExportActions.php?result=<id>&format=csv|json|print&enhanced=0|1, body only via_ctxBuilds the file from the stored rows and appends an element that pulls it
flows-export-chunkFlowExportActions.php?export=<token>&chunk=<n>, body only via_ctxSends the next 512 KiB of an export
flows-rawFlowActions.php?result=<id>&chunk=<n>Sends the next 512 KiB of the raw output
flows-summary-estimateFlowActions.phpthe query’s signalsThe estimate for the filtered totals
flows-summary-runFlowActions.phpthe query’s signalsComputes the filtered totals of the Summary tab (query kind flows-summary)
build-flows-graphFlowGraphActions.phpthe query’s signals, flows_graph_unitBuilds Traffic over time for the current filter, one nfdump per interval, one interval per free nfdump process (query kind flowsgraph)
touch-flows-graphFlowGraphActions.phpflows_graph_unitRe-renders after a client-side change; reads nothing

Conversations

ActionFileInputDoes
conversations-runConversationActions.phpconv_group (ip|net24|net16|port), conv_direction (both|forward), sankey_metric, sankey_topN, filter and byte limitsRuns the aggregation (query kind conversations), split into parallel time slices when the read is large. A Kill before nfdump starts or before the result is stored keeps the previous result and its notices
conversations-checkConversationActions.phpthe same signalsRecomputes _conv_stale only and reads no capture file; an effect on the query card’s signals posts it, so a filter applied from the drawer counts too

Filter builder

ActionFileInputDoes
drawer-openFilterDrawerActions.phpsignals drawer_target, drawer_filter, drawer_openValidates the text into _flt_drawer; the render adds the editor and the saved list
drawer-closeFilterDrawerActions.phpsignal drawer_openRe-renders the closed drawer
filter-saveFilterDrawerActions.phpsignals drawer_filter, drawer_nameSaves the editor’s text, named after itself when unnamed; a duplicate answers with a warning
filter-updateFilterDrawerActions.php?id=, optional &rename=1Updates name and expression, or with rename=1 only the name
filter-deleteFilterDrawerActions.php?id=Deletes a saved filter
filter-starFilterDrawerActions.php?id=&on=0|1Stars or unstars it
filter-useFilterDrawerActions.php?id=Loads the expression into the editor and marks the filter used
filter-migrate-localFilterDrawerActions.phpsignal drawer_importImports a browser’s old saved list

The drawer opens on the window event nfsen-open-drawer with {target: overview|talkers|flows|conversations|alert, tab: builder|raw|saved}; the filter fields’ Builder and Saved buttons dispatch it.

filter-migrate-local reads drawer_import and always clears it. When the import ran, or the list held nothing new, it sets the server-owned signal _drawer_imported to a fresh random id; a post with an empty drawer_import is not acknowledged, and a failure answers with an error-level _drawer_notice. The browser sets localStorage nfsen-filters-migrated only when _drawer_imported changes while its import is pending, so a failed, lost or unanswered post is retried on the next load.

Alerts

ActionFileInputDoes
save-alertAlertActions.phpthe alert_form_* signalsCreates or updates a rule (by id)
delete-alertAlertActions.php?id=Removes a rule and its state
toggle-alertAlertActions.php?id=, optional &enabled=true|falseSets a rule on or off; without enabled it flips
test-alertAlertActions.php?id=Evaluates the rule against the newest complete interval, records a test event, sends the notifications if it would fire (waiting up to 10 s for the webhook), and opens the result dialog with each channel’s delivery
save-alert-templatesAlertActions.phpthe four settings_default*Template signalsSaves the global notification templates

Health

ActionFileInputDoes
trigger-importImportActions.phpsignals admin_target_profile, import_scan_portsCatch-up import for a profile
backfill-importImportActions.phpthe sameRe-reads every capture without resetting, for a datasource that accepts historic writes (VictoriaMetrics)
force-rescanImportActions.phpthe sameResets and re-imports a profile (destructive, confirmation first; RRD)
cancel-importImportActions.phpnoneCancels a running manual import
topn-fillImportActions.phpnoneQueues the missing top-N intervals of every profile and source now
health-refreshImportActions.phpnoneRe-renders; the 10 s tick while Health is open

Settings

ActionFileInputDoes
save-settingsSettingsActions.php?scope=general|rdns, the settings_* signals and displayTzSaves the General tab (general), the reverse DNS switch (rdns), or both without a scope; merges into preferences.json, keeping the alert rules and templates

Query kinds

Every query that reads capture files runs through QueryRunner with a kind, which the progress signals (query_running, query_permille, query_status, query_eta, query_kind) report and which decides the page a Kill notice goes to: graph and overview-topn (Overview), stats and talkers-panel (Top Talkers), flows, flows-summary and flowsgraph (Flows), conversations (Conversations). The estimator records every finished run of a kind in query_runs, with the nfdump processes it read its files with and whether it needed a second pass. A split run’s query_status counts files (Read 120 of 288 files in 4 nfdump processes), and its final status names the processes.

An MCP client does not use these actions, which are bound to a browser tab’s signals. The optional MCP server exposes ten read-only tools over stdio or HTTP and calls the query layer directly.

Reading an action’s exact contract

The fastest way to see what signals an action reads and writes is the action closure itself: they’re short, and each starts by pulling its inputs with $c->getSignal('name') or $c->input('name'). There is no separate schema to keep in sync with them.