Platform

Platform overviewArchitectureWorkflow orchestrationGitOps configurationGovernance and AAAAI and MCPKnowledge and contextRuntime and executionEvidence and monitoring

Use cases

All use casesProduction incidentRelease preparationHotfix to productionSecurity scan triage
Why NopsAIIntegrationsSecurity

Resources

All resourcesAI agent governanceMCP governanceMCP securitySelf-hosted platforms
PricingGitHub

Company

How a run worksAboutContactBook a demo

Monitoring API

Analytics over runs, performance, AI usage and security, plus recommendations, alert rules, and saved views.

ReferenceOperatorAdministratorDeveloper

Key points

  • Every analytics route shares one filter model: a from/to window defaulting to the last 30 days, plus team, pipeline, branch, and status filters.
  • to must be after from, and an unparseable window is a 400 naming which half failed.
  • Results are filtered per caller, so a summary is what this caller may see rather than a platform total.
  • compare=true adds the preceding window of equal length, which is what turns a number into a signal.
  • AI usage covers assistant and evaluation spend alongside pipeline runs — it is the whole AI bill.
  • Acknowledged and resolved are different recommendation states: one says "we know", the other says "it is fixed".
  • Evaluating an alert rule by hand does not fire notifications, which makes it safe to test a threshold.
  • A saved view stores filters rather than results, so it always reflects current data.

Operations

GET/v1/monitoring/summaryAuthorized

Run counts and success rate for a window.

Notes

Counts are filtered per caller, so a summary is what this caller may see rather than a platform total.

Parameters

NameInTypeRequiredDescription
fromquerytimestampOptionalStart of the analysis window. The default window is the last 30 days.Default: 30 days ago
toquerytimestampOptionalEnd of the analysis window. Must be after from.Default: now
teamIdquerystringOptionalRestrict to one team. team_id is accepted as an alias.
pipelineNamequerystringOptionalRestrict to one pipeline.
statusquerystringOptionalRestrict to runs in one status.
branchquerystringOptionalRestrict to one Git ref.

Call it

Read the operational summaryapi-monitoring request
curl -s -H "Authorization: Bearer $NOPSAI_TOKEN" "$NOPSAI_URL/v1/monitoring/summary?from=2026-08-01" | jq
Result

Counts per terminal state plus the success rate over the window.

Responses

200application/json

Run counts for the window.

{
  "window": { "from": "2026-07-20T00:00:00Z", "to": "2026-08-19T00:00:00Z" },
  "total_runs": 412,
  "successful_runs": 388,
  "failed_runs": 17,
  "cancelled_runs": 3,
  "running_runs": 2,
  "waiting_approval_runs": 1,
  "success_rate": 0.94
}

When it fails

StatusCauseWhat to do
400An unparseable from or to, or a to that is not after from.The message names which of the two failed.
500The analytics query failed.Platform fault.

Side effects

  • None.

Proven by

  • services/nopsai/monitoring_analytics_handlers_test.go
  • services/nopsai/monitoring_analytics_handlers.go
GET/v1/monitoring/runs/analyticsAuthorized

Run trends and breakdowns over a window.

Notes

compare=true is what turns a number into a signal: 94% success means little without last month beside it.

Parameters

NameInTypeRequiredDescription
fromquerytimestampOptionalStart of the analysis window. The default window is the last 30 days.Default: 30 days ago
toquerytimestampOptionalEnd of the analysis window. Must be after from.Default: now
teamIdquerystringOptionalRestrict to one team. team_id is accepted as an alias.
pipelineNamequerystringOptionalRestrict to one pipeline.
comparequerybooleanOptionalInclude the previous equivalent window for comparison.
triggerSourcequerystringOptionalRestrict to runs from one entry point.

Call it

Compare this window with the lastapi-monitoring request
curl -s -H "Authorization: Bearer $NOPSAI_TOKEN" "$NOPSAI_URL/v1/monitoring/runs/analytics?from=2026-08-01&compare=true" | jq
Result

Trends for the window and, with compare, the preceding one of equal length.

Responses

200application/json

Run analytics.

{
  "window": { "from": "2026-07-20T00:00:00Z", "to": "2026-08-19T00:00:00Z" },
  "total_runs": 412,
  "successful_runs": 388,
  "failed_runs": 17,
  "cancelled_runs": 3,
  "running_runs": 2,
  "waiting_approval_runs": 1,
  "success_rate": 0.94
}

When it fails

StatusCauseWhat to do
400An invalid window or filter value.The message names the parameter.
500The query failed.Platform fault.

Side effects

  • None.

Proven by

  • services/nopsai/monitoring_analytics_handlers_test.go
  • services/nopsai/monitoring_analytics_handlers.go
GET/v1/monitoring/pipelines/performanceAuthorized

Duration statistics per pipeline.

Notes

Read p95 rather than the average. A pipeline with a 3-minute average and a 12-minute p95 is the one people complain about.

Parameters

NameInTypeRequiredDescription
fromquerytimestampOptionalStart of the analysis window. The default window is the last 30 days.Default: 30 days ago
toquerytimestampOptionalEnd of the analysis window. Must be after from.Default: now
teamIdquerystringOptionalRestrict to one team. team_id is accepted as an alias.
pipelineNamequerystringOptionalRestrict to one pipeline.
minDurationSecondsquerynumberOptionalOnly runs at least this long.
maxDurationSecondsquerynumberOptionalOnly runs at most this long.

Call it

Find the slowest pipelinesapi-monitoring request
curl -s -H "Authorization: Bearer $NOPSAI_TOKEN" "$NOPSAI_URL/v1/monitoring/pipelines/performance" | jq '.items | sort_by(-.p95_seconds) | .[0:5]'
Result

Average, median, and p95 per pipeline over the window.

Responses

200application/json

Per-pipeline duration statistics.

{
  "window": { "from": "2026-07-20T00:00:00Z", "to": "2026-08-19T00:00:00Z" },
  "items": [
    {
      "name": "release-service",
      "runs": 84,
      "average_seconds": 196.4,
      "median_seconds": 181.0,
      "p95_seconds": 402.7
    }
  ]
}

When it fails

StatusCauseWhat to do
400An invalid window or duration filter.The message names the parameter.
500The query failed.Platform fault.

Side effects

  • None.

Proven by

  • services/nopsai/monitoring_analytics_handlers_test.go
  • services/nopsai/monitoring_analytics_handlers.go
GET/v1/monitoring/steps/performanceAuthorized

Duration statistics per step.

Parameters

NameInTypeRequiredDescription
fromquerytimestampOptionalStart of the analysis window. The default window is the last 30 days.Default: 30 days ago
toquerytimestampOptionalEnd of the analysis window. Must be after from.Default: now
teamIdquerystringOptionalRestrict to one team. team_id is accepted as an alias.
pipelineNamequerystringOptionalRestrict to one pipeline.
stepNamequerystringOptionalRestrict to one step. step_name is accepted as an alias.

Call it

Find the slow step inside a pipelineapi-monitoring request
curl -s -H "Authorization: Bearer $NOPSAI_TOKEN" "$NOPSAI_URL/v1/monitoring/steps/performance?pipelineName=release-service" | jq
Result

Per-step statistics, which is how a slow pipeline is narrowed to one step.

Responses

200application/json

Per-step duration statistics.

{
  "window": { "from": "2026-07-20T00:00:00Z", "to": "2026-08-19T00:00:00Z" },
  "items": [
    {
      "name": "release-service",
      "runs": 84,
      "average_seconds": 196.4,
      "median_seconds": 181.0,
      "p95_seconds": 402.7
    }
  ]
}

When it fails

StatusCauseWhat to do
400An invalid window or filter.The message names the parameter.
500The query failed.Platform fault.

Side effects

  • None.

Proven by

  • services/nopsai/monitoring_analytics_handlers_test.go
  • services/nopsai/monitoring_analytics_handlers.go
GET/v1/monitoring/tasks/performanceAuthorized

Duration statistics per task.

Notes

A step is only as fast as its slowest task, so a wide spread here means the step is waiting on one outlier.

Parameters

NameInTypeRequiredDescription
fromquerytimestampOptionalStart of the analysis window. The default window is the last 30 days.Default: 30 days ago
toquerytimestampOptionalEnd of the analysis window. Must be after from.Default: now
teamIdquerystringOptionalRestrict to one team. team_id is accepted as an alias.
pipelineNamequerystringOptionalRestrict to one pipeline.
taskNamequerystringOptionalRestrict to one task. task_name is accepted as an alias.

Call it

Compare tasks inside a stepapi-monitoring request
curl -s -H "Authorization: Bearer $NOPSAI_TOKEN" "$NOPSAI_URL/v1/monitoring/tasks/performance?stepName=checks" | jq
Result

Per-task statistics, which shows whether concurrency is actually helping.

Responses

200application/json

Per-task duration statistics.

{
  "window": { "from": "2026-07-20T00:00:00Z", "to": "2026-08-19T00:00:00Z" },
  "items": [
    {
      "name": "release-service",
      "runs": 84,
      "average_seconds": 196.4,
      "median_seconds": 181.0,
      "p95_seconds": 402.7
    }
  ]
}

When it fails

StatusCauseWhat to do
400An invalid window or filter.The message names the parameter.
500The query failed.Platform fault.

Side effects

  • None.

Proven by

  • services/nopsai/monitoring_analytics_handlers_test.go
  • services/nopsai/monitoring_analytics_handlers.go
GET/v1/monitoring/triggers/analyticsAuthorized

How runs are being started, by trigger.

Parameters

NameInTypeRequiredDescription
fromquerytimestampOptionalStart of the analysis window. The default window is the last 30 days.Default: 30 days ago
toquerytimestampOptionalEnd of the analysis window. Must be after from.Default: now
teamIdquerystringOptionalRestrict to one team. team_id is accepted as an alias.
triggerSourcequerystringOptionalRestrict to one entry point.

Call it

See which triggers are firingapi-monitoring request
curl -s -H "Authorization: Bearer $NOPSAI_TOKEN" "$NOPSAI_URL/v1/monitoring/triggers/analytics" | jq
Result

Run counts grouped by how they started.

Responses

200application/json

Trigger analytics.

{
  "window": { "from": "2026-07-20T00:00:00Z", "to": "2026-08-19T00:00:00Z" },
  "total_runs": 412,
  "successful_runs": 388,
  "failed_runs": 17,
  "cancelled_runs": 3,
  "running_runs": 2,
  "waiting_approval_runs": 1,
  "success_rate": 0.94
}

When it fails

StatusCauseWhat to do
400An invalid window or filter.The message names the parameter.
500The query failed.Platform fault.

Side effects

  • None.

Proven by

  • services/nopsai/monitoring_analytics_handlers_test.go
  • services/nopsai/monitoring_analytics_handlers.go
GET/v1/monitoring/external-triggers/analyticsAuthorized

Invocation analytics for external API triggers.

Notes

Aggregate counts live here; the per-call reasons live in the trigger’s own invocation history.

Parameters

NameInTypeRequiredDescription
fromquerytimestampOptionalStart of the analysis window. The default window is the last 30 days.Default: 30 days ago
toquerytimestampOptionalEnd of the analysis window. Must be after from.Default: now
teamIdquerystringOptionalRestrict to one team. team_id is accepted as an alias.
externalTriggerIdquerystringOptionalRestrict to one external trigger.

Call it

See how an integration is behavingapi-monitoring request
curl -s -H "Authorization: Bearer $NOPSAI_TOKEN" "$NOPSAI_URL/v1/monitoring/external-triggers/analytics" | jq
Result

Invocation counts and outcomes per trigger.

Responses

200application/json

External trigger analytics.

{
  "window": { "from": "2026-07-20T00:00:00Z", "to": "2026-08-19T00:00:00Z" },
  "total_runs": 412,
  "successful_runs": 388,
  "failed_runs": 17,
  "cancelled_runs": 3,
  "running_runs": 2,
  "waiting_approval_runs": 1,
  "success_rate": 0.94
}

When it fails

StatusCauseWhat to do
400An invalid window or trigger id.The message names the parameter.
500The query failed.Platform fault.

Side effects

  • None.

Proven by

  • services/nopsai/monitoring_analytics_handlers_test.go
  • services/nopsai/monitoring_analytics_handlers.go
GET/v1/monitoring/ai-usageAuthorized

Token and model usage across runs and the assistant.

Notes

Assistant and evaluation spend is recorded alongside pipeline spend, so this is the whole AI bill rather than the pipeline part of it.

Parameters

NameInTypeRequiredDescription
fromquerytimestampOptionalStart of the analysis window. The default window is the last 30 days.Default: 30 days ago
toquerytimestampOptionalEnd of the analysis window. Must be after from.Default: now
teamIdquerystringOptionalRestrict to one team. team_id is accepted as an alias.
pipelineNamequerystringOptionalRestrict to one pipeline.
providerquerystringOptionalRestrict to one provider.
modelquerystringOptionalRestrict to one model.
featurequerystringOptionalRestrict to one consuming surface, such as pipeline runs or the assistant.

Call it

See where the money is goingapi-monitoring request
curl -s -H "Authorization: Bearer $NOPSAI_TOKEN" "$NOPSAI_URL/v1/monitoring/ai-usage?from=2026-08-01" | jq '{window, by_pipeline}'
Result

Total spend plus breakdowns by pipeline, task, and the most expensive runs.

Responses

200application/json

AI spend totals and breakdowns. unpriced_calls counts calls that could not be priced and are therefore missing from spend_usd.

{
  "window": { "from": "2026-08-01T00:00:00Z", "to": "2026-08-19T00:00:00Z" },
  "spend_usd": 128.44,
  "priced_calls": 3120,
  "unpriced_calls": 0,
  "by_pipeline": [{ "key": "release-service", "label": "release-service", "count": 412, "cost_usd": 61.20 }]
}

When it fails

StatusCauseWhat to do
400An invalid window or filter.The message names the parameter.
500The usage query failed.Platform fault.

Side effects

  • None.

Proven by

  • services/nopsai/monitoring_analytics_handlers_test.go
  • services/nopsai/monitoring_analytics_handlers.go
GET/v1/monitoring/reliabilityAuthorized

Reliability view: what fails, how often, and where.

Parameters

NameInTypeRequiredDescription
fromquerytimestampOptionalStart of the analysis window. The default window is the last 30 days.Default: 30 days ago
toquerytimestampOptionalEnd of the analysis window. Must be after from.Default: now
teamIdquerystringOptionalRestrict to one team. team_id is accepted as an alias.
pipelineNamequerystringOptionalRestrict to one pipeline.

Call it

Read the reliability viewapi-monitoring request
curl -s -H "Authorization: Bearer $NOPSAI_TOKEN" "$NOPSAI_URL/v1/monitoring/reliability" | jq
Result

Failure concentrations by pipeline and step over the window.

Responses

200application/json

Reliability analytics.

{
  "window": { "from": "2026-07-20T00:00:00Z", "to": "2026-08-19T00:00:00Z" },
  "total_runs": 412,
  "successful_runs": 388,
  "failed_runs": 17,
  "cancelled_runs": 3,
  "running_runs": 2,
  "waiting_approval_runs": 1,
  "success_rate": 0.94
}

When it fails

StatusCauseWhat to do
400An invalid window.Check from and to.
500The query failed.Platform fault.

Side effects

  • None.

Proven by

  • services/nopsai/monitoring_analytics_handlers_test.go
  • services/nopsai/monitoring_analytics_handlers.go
GET/v1/monitoring/efficiencyAuthorized

Efficiency view: time and capacity spent per unit of work.

Notes

Queue time and approval waits are not execution time. Efficiency separates them so "the pipeline is slow" can be answered honestly.

Parameters

NameInTypeRequiredDescription
fromquerytimestampOptionalStart of the analysis window. The default window is the last 30 days.Default: 30 days ago
toquerytimestampOptionalEnd of the analysis window. Must be after from.Default: now
teamIdquerystringOptionalRestrict to one team. team_id is accepted as an alias.
pipelineNamequerystringOptionalRestrict to one pipeline.

Call it

Read the efficiency viewapi-monitoring request
curl -s -H "Authorization: Bearer $NOPSAI_TOKEN" "$NOPSAI_URL/v1/monitoring/efficiency" | jq
Result

Where run time is going, including waiting rather than working.

Responses

200application/json

Efficiency analytics.

{
  "window": { "from": "2026-07-20T00:00:00Z", "to": "2026-08-19T00:00:00Z" },
  "items": [
    {
      "name": "release-service",
      "runs": 84,
      "average_seconds": 196.4,
      "median_seconds": 181.0,
      "p95_seconds": 402.7
    }
  ]
}

When it fails

StatusCauseWhat to do
400An invalid window.Check from and to.
500The query failed.Platform fault.

Side effects

  • None.

Proven by

  • services/nopsai/monitoring_analytics_handlers_test.go
  • services/nopsai/monitoring_analytics_handlers.go
GET/v1/monitoring/securityAuthorized

Security view: authorization denials and sensitive access over a window.

Notes

This aggregates; the audit log has the individual records, including who read which secret.

Parameters

NameInTypeRequiredDescription
fromquerytimestampOptionalStart of the analysis window. The default window is the last 30 days.Default: 30 days ago
toquerytimestampOptionalEnd of the analysis window. Must be after from.Default: now
teamIdquerystringOptionalRestrict to one team. team_id is accepted as an alias.

Call it

Read the security viewapi-monitoring request
curl -s -H "Authorization: Bearer $NOPSAI_TOKEN" "$NOPSAI_URL/v1/monitoring/security" | jq
Result

Denials and sensitive operations aggregated over the window.

Responses

200application/json

Security analytics.

{
  "window": { "from": "2026-07-20T00:00:00Z", "to": "2026-08-19T00:00:00Z" },
  "total_runs": 412,
  "successful_runs": 388,
  "failed_runs": 17,
  "cancelled_runs": 3,
  "running_runs": 2,
  "waiting_approval_runs": 1,
  "success_rate": 0.94
}

When it fails

StatusCauseWhat to do
400An invalid window.Check from and to.
500The query failed.Platform fault.

Side effects

  • None.

Proven by

  • services/nopsai/monitoring_analytics_handlers_test.go
  • services/nopsai/monitoring_analytics_handlers.go
GET/v1/monitoring/dispatcherAuthenticated

Live dispatcher and runner fleet status.

Notes

Authenticated rather than authorized: any signed-in caller may see whether there is anywhere to run work.

Call it

Check the fleetapi-monitoring request
curl -s -H "Authorization: Bearer $NOPSAI_TOKEN" "$NOPSAI_URL/v1/monitoring/dispatcher" | jq '.runners'
Result

Registered runners with their scopes, capacity, and reachability.

Responses

200application/json

Dispatcher and fleet state.

{
  "runners": [
    { "runner_id": "runner-local-1", "scopes": ["prod"], "capacity": 2, "reachable": true, "dispatch_enabled": true }
  ]
}

Side effects

  • None.

Proven by

  • services/nopsai/monitoring_handlers_test.go
  • services/nopsai/monitoring_handlers.go
GET/v1/monitoring/runners/historyAuthorized

Runner connection and capacity history.

Notes

A run that queued for a long time and then succeeded usually shows up here as a runner that was away.

Parameters

NameInTypeRequiredDescription
fromquerytimestampOptionalStart of the analysis window. The default window is the last 30 days.Default: 30 days ago
toquerytimestampOptionalEnd of the analysis window. Must be after from.Default: now
runnerIdquerystringOptionalRestrict to one runner.

Call it

Check whether a runner has been flappingapi-monitoring request
curl -s -H "Authorization: Bearer $NOPSAI_TOKEN" "$NOPSAI_URL/v1/monitoring/runners/history" | jq
Result

Connect and disconnect events over the window, which is how intermittent capacity is spotted.

Responses

200application/json

Runner history.

[
  { "runner_id": "runner-local-1", "event": "connected", "at": "2026-08-19T08:11:04Z" }
]

When it fails

StatusCauseWhat to do
400An invalid window.Check from and to.
500The query failed.Platform fault.

Side effects

  • None.

Proven by

  • services/nopsai/monitoring_handlers_test.go
  • services/nopsai/monitoring_handlers.go
GET/v1/monitoring/recommendationsAuthorized

Lists platform recommendations derived from monitoring data.

Parameters

NameInTypeRequiredDescription
statusquerystringOptionalRestrict to open, acknowledged, or resolved recommendations.

Call it

List open recommendationsapi-monitoring request
curl -s -H "Authorization: Bearer $NOPSAI_TOKEN" "$NOPSAI_URL/v1/monitoring/recommendations?status=open" | jq
Result

Findings with their severity and what they suggest.

Responses

200application/json

Recommendations.

[
  {
    "id": "9a2c...",
    "severity": "medium",
    "title": "release-service p95 doubled",
    "status": "open"
  }
]

When it fails

StatusCauseWhat to do
500The query failed.Platform fault.

Side effects

  • None.

Proven by

  • services/nopsai/monitoring_handlers_test.go
  • services/nopsai/monitoring_handlers.go
POST/v1/monitoring/recommendations/{recommendationID}/acknowledgeAuthorized

Acknowledges a recommendation without resolving it.

Notes

Acknowledged and resolved are different states on purpose: one says "we know", the other says "it is fixed".

Parameters

NameInTypeRequiredDescription
recommendationIDpathstringRequiredRecommendation identifier.

Call it

Acknowledge a recommendationapi-monitoring request
curl -sX POST -H "Authorization: Bearer $NOPSAI_TOKEN" "$NOPSAI_URL/v1/monitoring/recommendations/$RECOMMENDATION_ID/acknowledge" | jq
Result

The recommendation moves to acknowledged: seen, not yet fixed.

Responses

200application/json

Recommendation acknowledged.

{ "id": "9a2c...", "status": "acknowledged" }

When it fails

StatusCauseWhat to do
404No recommendation with that id.Confirm the id from the list.
500The update failed.Retry.

Side effects

  • Records who acknowledged it and when.

Proven by

  • services/nopsai/monitoring_handlers_test.go
  • services/nopsai/monitoring_handlers.go
POST/v1/monitoring/recommendations/{recommendationID}/resolveAuthorized

Marks a recommendation resolved.

Parameters

NameInTypeRequiredDescription
recommendationIDpathstringRequiredRecommendation identifier.

Call it

Resolve a recommendationapi-monitoring request
curl -sX POST -H "Authorization: Bearer $NOPSAI_TOKEN" "$NOPSAI_URL/v1/monitoring/recommendations/$RECOMMENDATION_ID/resolve" | jq
Result

The recommendation is closed. It can reappear if the underlying signal returns.

Responses

200application/json

Recommendation resolved.

{ "id": "9a2c...", "status": "resolved" }

When it fails

StatusCauseWhat to do
404No recommendation with that id.Confirm the id.
500The update failed.Retry.

Side effects

  • Closes the finding. A recurring signal produces a new recommendation rather than reopening this one.

Proven by

  • services/nopsai/monitoring_handlers_test.go
  • services/nopsai/monitoring_handlers.go
GET/v1/monitoring/alert-rulesAuthorized

Lists alert rules.

Call it

List alert rulesapi-monitoring request
curl -s -H "Authorization: Bearer $NOPSAI_TOKEN" "$NOPSAI_URL/v1/monitoring/alert-rules" | jq
Result

Each rule with its condition and whether it is enabled.

Responses

200application/json

Alert rules.

[
  {
    "id": "b41d...",
    "name": "release-service failure rate",
    "enabled": true
  }
]

When it fails

StatusCauseWhat to do
500The query failed.Platform fault.

Side effects

  • None.

Proven by

  • services/nopsai/monitoring_handlers_test.go
  • services/nopsai/monitoring_handlers.go
POST/v1/monitoring/alert-rulesAuthorized

Creates an alert rule.

Call it

Create an alert ruleapi-monitoring request
curl -sX POST "$NOPSAI_URL/v1/monitoring/alert-rules" \
  -H "Authorization: Bearer $NOPSAI_TOKEN" \
  -H "Content-Type: application/json" \
  --data @rule.json | jq -r .id
Result

The created rule. Evaluate it once before trusting it.

Replace before running
  • rule.json carries the rule name, its condition, and the window it evaluates over.

Responses

201application/json

Rule created.

{ "id": "b41d...", "name": "release-service failure rate", "enabled": true }

When it fails

StatusCauseWhat to do
400An invalid condition or window.The message names the field.
500The rule could not be stored.Retry.

Side effects

  • Creates a rule the platform evaluates on its own schedule.
  • Writes an audit record.

Proven by

  • services/nopsai/monitoring_handlers_test.go
  • services/nopsai/monitoring_handlers.go
PUT/v1/monitoring/alert-rules/{ruleID}Authorized

Replaces an alert rule.

Parameters

NameInTypeRequiredDescription
ruleIDpathstringRequiredRule identifier.

Call it

Update an alert ruleapi-monitoring request
curl -sX PUT "$NOPSAI_URL/v1/monitoring/alert-rules/$RULE_ID" \
  -H "Authorization: Bearer $NOPSAI_TOKEN" \
  -H "Content-Type: application/json" \
  --data @rule.json | jq
Result

The stored rule.

Responses

200application/json

Rule stored.

{ "id": "b41d...", "name": "release-service failure rate", "enabled": true }

When it fails

StatusCauseWhat to do
400An invalid condition.Evaluate the rule to see what it would match.
404No rule with that id.Confirm the id.
500The update failed.Retry.

Side effects

  • Changes what fires and when.
  • Writes an audit record.

Proven by

  • services/nopsai/monitoring_handlers_test.go
  • services/nopsai/monitoring_handlers.go
DELETE/v1/monitoring/alert-rules/{ruleID}Authorized

Deletes an alert rule.

Parameters

NameInTypeRequiredDescription
ruleIDpathstringRequiredRule to delete.

Call it

Delete an alert ruleapi-monitoring request
curl -sX DELETE -H "Authorization: Bearer $NOPSAI_TOKEN" "$NOPSAI_URL/v1/monitoring/alert-rules/$RULE_ID" -w "%{http_code}\n"
Result

204. Events it already produced stay.

Responses

204

Rule deleted.

When it fails

StatusCauseWhat to do
404No rule with that id.It may already be deleted.
500The delete failed.Retry.

Side effects

  • Stops future evaluation. Past alert events remain.
  • Writes an audit record.

Proven by

  • services/nopsai/monitoring_handlers_test.go
  • services/nopsai/monitoring_handlers.go
POST/v1/monitoring/alert-rules/{ruleID}/evaluateAuthorized

Evaluates a rule now, without waiting for its schedule.

Notes

Always evaluate a new rule before enabling it. A threshold that matches everything is indistinguishable from one that matches nothing until it runs.

Parameters

NameInTypeRequiredDescription
ruleIDpathstringRequiredRule to evaluate.

Call it

Test a rule against current dataapi-monitoring request
curl -sX POST -H "Authorization: Bearer $NOPSAI_TOKEN" "$NOPSAI_URL/v1/monitoring/alert-rules/$RULE_ID/evaluate" | jq
Result

Whether the rule matches right now — the way to check a threshold before it pages someone at 3am.

Responses

200application/json

Evaluation result.

{ "id": "b41d...", "matched": false, "observed": 0.03 }

When it fails

StatusCauseWhat to do
400The rule cannot be evaluated as written.The message names the problem in the condition.
404No rule with that id.Confirm the id.
500Evaluation failed.Platform fault.

Side effects

  • Evaluates against live data. A manual evaluation does not fire notifications.

Proven by

  • services/nopsai/monitoring_handlers_test.go
  • services/nopsai/monitoring_handlers.go
GET/v1/monitoring/alert-eventsAuthorized

Lists alert events that rules have produced.

Notes

Events record the observed value, so a rule that fires constantly can be retuned from evidence rather than guesswork.

Parameters

NameInTypeRequiredDescription
fromquerytimestampOptionalStart of the analysis window. The default window is the last 30 days.Default: 30 days ago
toquerytimestampOptionalEnd of the analysis window. Must be after from.Default: now
ruleIdquerystringOptionalRestrict to events from one rule.

Call it

Read recent alert eventsapi-monitoring request
curl -s -H "Authorization: Bearer $NOPSAI_TOKEN" "$NOPSAI_URL/v1/monitoring/alert-events" | jq
Result

What fired, when, and what the rule observed at the time.

Responses

200application/json

Alert events.

[
  { "rule_id": "b41d...", "fired_at": "2026-08-18T02:14:00Z", "observed": 0.21 }
]

When it fails

StatusCauseWhat to do
400An invalid window.Check from and to.
500The query failed.Platform fault.

Side effects

  • None.

Proven by

  • services/nopsai/monitoring_handlers_test.go
  • services/nopsai/monitoring_handlers.go
GET/v1/monitoring/viewsAuthorized

Lists saved monitoring views.

Call it

List saved viewsapi-monitoring request
curl -s -H "Authorization: Bearer $NOPSAI_TOKEN" "$NOPSAI_URL/v1/monitoring/views" | jq
Result

Named filter sets, so a recurring investigation is one click rather than six parameters.

Responses

200application/json

Saved views.

[{
  "id": "6c1f2a90-3b77-4d22-9a51-8e2b0c4f7d31",
  "name": "Failing releases",
  "filters": { "pipelineName": "release-service", "status": "failure" }
}]

When it fails

StatusCauseWhat to do
500The query failed.Platform fault.

Side effects

  • None.

Proven by

  • services/nopsai/monitoring_handlers_test.go
  • services/nopsai/monitoring_handlers.go
POST/v1/monitoring/viewsAuthorized

Saves a monitoring view.

Notes

A view stores filters, not results, so it always reflects current data.

Call it

Save a filter setapi-monitoring request
curl -sX POST "$NOPSAI_URL/v1/monitoring/views" \
  -H "Authorization: Bearer $NOPSAI_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"Failing releases","filters":{"pipelineName":"release-service","status":"failure"}}' | jq -r .id
Result

The saved view id.

Responses

201application/json

View saved.

{
  "id": "6c1f2a90-3b77-4d22-9a51-8e2b0c4f7d31",
  "name": "Failing releases",
  "filters": { "pipelineName": "release-service", "status": "failure" }
}

When it fails

StatusCauseWhat to do
400A missing name or unusable filter set.Filters use the same parameter names as the analytics routes.
500The view could not be saved.Retry.

Side effects

  • Stores a named filter set.

Proven by

  • services/nopsai/monitoring_handlers_test.go
  • services/nopsai/monitoring_handlers.go
PUT/v1/monitoring/views/{viewID}Authorized

Replaces a saved view.

Parameters

NameInTypeRequiredDescription
viewIDpathuuidRequiredView identifier.

Call it

Update a saved viewapi-monitoring request
curl -sX PUT "$NOPSAI_URL/v1/monitoring/views/$VIEW_ID" \
  -H "Authorization: Bearer $NOPSAI_TOKEN" \
  -H "Content-Type: application/json" \
  --data @view.json | jq
Result

The stored view.

Responses

200application/json

View stored.

{
  "id": "6c1f2a90-3b77-4d22-9a51-8e2b0c4f7d31",
  "name": "Failing releases",
  "filters": { "pipelineName": "release-service", "status": "failure" }
}

When it fails

StatusCauseWhat to do
400An unusable filter set.The message names the field.
404No view with that id.Confirm the id.
500The update failed.Retry.

Side effects

  • None beyond storing the filters.

Proven by

  • services/nopsai/monitoring_handlers_test.go
  • services/nopsai/monitoring_handlers.go
DELETE/v1/monitoring/views/{viewID}Authorized

Deletes a saved view.

Parameters

NameInTypeRequiredDescription
viewIDpathuuidRequiredView to delete.

Call it

Delete a saved viewapi-monitoring request
curl -sX DELETE -H "Authorization: Bearer $NOPSAI_TOKEN" "$NOPSAI_URL/v1/monitoring/views/$VIEW_ID" -w "%{http_code}\n"
Result

204.

Responses

204

View deleted.

When it fails

StatusCauseWhat to do
400The id is malformed.Use an id from the list.
404No view with that id.It may already be deleted.
500The delete failed.Retry.

Side effects

  • Removes the saved filter set. No monitoring data is affected.

Proven by

  • services/nopsai/monitoring_handlers_test.go
  • services/nopsai/monitoring_handlers.go

How it works

Read p95 rather than the average when chasing a slow pipeline: a three-minute average with a twelve-minute p95 is the one people complain about, and the average hides it. The pipeline, step, and task performance routes are the same question at three depths, which is how a slow pipeline is narrowed to a single task.

Efficiency separates waiting from working. Queue time and approval waits are not execution time, so "the pipeline is slow" can be answered honestly rather than by optimising steps that were never the problem.

The security view aggregates; the audit log holds the individual records. Reach for the view to see a pattern and the log to see who did what — including who read which secret.

Test an alert rule with the evaluate route before enabling it. A threshold that matches everything looks exactly like one that matches nothing until it runs, and the difference is discovered at 3am.

Implementation evidence

  • services/nopsai/monitoring_analytics_handlers.go

    Window and filter parsing, analytics responses.

  • services/nopsai/monitoring_handlers.go

    Dispatcher status, recommendations, alert rules, and saved views.