The classification service interprets a Universal Pole Model — it reads what’s on the pole and tells you what kind of structure it is. Clearance, sag, and guying all depend on the classifications it produces, but you can also call it directly when you want a labeled pole without running a full analysis pass.

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 /circuit-classify

Classify each circuit on the pole by voltage class (communication, secondary, primary, sub-transmission, transmission). Honors both attachment voltage and SPIDA usage_group when present.

POST /framing-classify

Identify the framing configuration per circuit — horizontal, vertical, triangular, single pin-insulator, dead-end, double-arm. Works from crossarm geometry first, falling back to attachment-string heuristics when arms aren’t present.

POST /framing-validate

Validate the detected framing against the load case and flag mismatches — for example, a single pin-insulator on a small angle line where the framing standard calls for a deadend.

POST /guying-validate

Walks every crossarm and pole-mounted insulator to compute the conductor tensions present at the pole, derives required guy directions, then checks whether the declared guying covers them.

curl https://$VERTICAL_AI_BASE_URL/guying-validate \
  -H "Authorization: Bearer $VERTICAL_AI_KEY" \
  -H "Content-Type: application/json" \
  -d @pole-model.json

POST /span-clearance-validate

Midspan vertical-separation validation between adjacent crossarms at each code state. This is the same call the clearance API’s /midspan endpoint wraps when invoked from the gateway.

Response shape

All endpoints return findings with the same envelope as the clearance service:

{
  "verdict": "pass | fail | indeterminate",
  "findings": [
    {
      "id": "framing-validate-pole12-xa2",
      "code_state": "NESC heavy",
      "severity": "code_violation | warning | info",
      "summary": "Single pin-insulator framing on 15° line angle",
      "evidence": { ... }
    }
  ],
  "proposals": [
    { "action": "swap_framing", "to": "double-deadend", "id": "..." }
  ]
}

For guying validation specifically, the response carries required_guys[] with per-guy status (covered, missing, under-strength). Aggregate verdicts roll up at the pole level, not the crossarm level.

See also