The sag service computes static sag profiles between two endpoints (or across an entire multi-pole line) with terrain sampling under the wire. It’s what backs the in-app sag viewer and the agent’s run_sag_analysis tool.

Direct REST access requires Tier B onboarding. URLs and bearer-token credentials are issued during embedder onboarding — until then, route equivalent calls through the Overhead gateway →. Email hello@epcstudio.io to start.

Endpoints

POST /static-sag

Single-span static sag.

{
  "endpoint_a": { "lat": 37.78, "lng": -122.41, "attachment_height_ft": 35 },
  "endpoint_b": { "lat": 37.79, "lng": -122.40, "attachment_height_ft": 33 },
  "conductor": { "id": "ACSR-336.4-Linnet" },
  "load_case": { "code": "GO-95", "district": "HEAVY" }
}

Returns the sag profile points, lowest-point ground clearance, and a per-conductor GO-95 Table 1 case-4 verdict.

POST /whole-line

Multi-pole project run. Same shape as /static-sag but accepts a list of poles and connections. Returns per-span profiles, lowest span-to-ground and span-to-span clearance reporting, and a line-wide max-sag summary.

POST /span-clearance

Midspan vertical separation between conductor pairs at every NESC / GO-95 code state. Emits retension and set_slack_tension proposals when separation collapses at sag.

POST /weather-sweep

Forecast-driven storm-readiness check. Pulls hourly wind / gust / temperature / ice for every pole’s lat/lon through a provider chain — Tomorrow.io (paid, native ice forecasts) → NWS (US-only, free) → Open-Meteo (wind-only, global fallback) — then runs the per-(pole, hour) loading sweep through the tightened solver. Returns a worst-hour summary per pole with the driving frame (wind speed, gust, ice radial, temperature, dominant driver) plus component-level safety factors.

Jurisdiction is auto-picked per pole from lat/lon — California poles run GO-95 Rule 44.1 SFs, everywhere else runs NESC 261. Construction grade (A / B / C) is derived from the pole’s attachments and crossing context (GO-95 Rule 42 Table 3 / NESC 242), not pinned from a caller-supplied loadcase.

{
  "pole_models": [ { ... }, { ... } ],
  "hours_ahead": 72,
  "failure_threshold_pct": 100.0
}

GET /conductor-catalog

Returns the default conductor catalog used as a reference when the source file’s wire properties are incomplete. Substring-style search with ?q=...&family=...&size=...&limit=25. Ambiguous queries return all matches — the caller picks.

Terrain

Every span is sampled against Google’s elevation API and the resulting ribbon is returned with the profile points. The viewer renders this as a translucent strip under the wire so you can see exactly where the lowest clearance sits.

Verdicts

Each conductor in a span gets one of:

  • pass — clearance meets the code at every sag state
  • fail — at least one state violates the code with margin > tolerance
  • marginal — passes but inside the margin band (configurable per tenant)

Verdicts attach to the response so callers can render red/yellow/green in their own UI without re-running the rule logic.

See also