This is the direct path: you hold the test data yourself and want a document. Nothing is stored, and no database plan is required.
Request#
| Field | Type | Default |
|---|---|---|
assets | array | []. The devices to render (see below). |
output_format | string | "pdf" · also "excel" |
report_depth | string | "standard" · also "basic", "comprehensive" |
include_summary | boolean | true. Set false to skip the AI narrative |
service_class | string | "acceptance" · also "maintenance". Selects the governing standard named on the report: "acceptance" is ANSI/NETA ATS-2021, "maintenance" is ANSI/NETA MTS-2023. An unrecognised value falls back to "acceptance". |
standard | string | Derived from service_class. Any value you send is ignored. |
job_name, job_number, date | string | "" |
technician, supervisor, client | string | "" |
project_number, work_order, report_number | string | "" |
cover_letter | string | "", optional body text on the cover |
report_depth | Contains |
|---|---|
basic | Cover, summary statistics, pass/fail table. |
standard | The above plus detailed test tables per asset. |
comprehensive | The above plus equipment lifespan, narrative and a maintenance schedule. |
include_summary: false is the fast path
The executive summary is the only part of a report that calls a language model, and it is most of the wall-clock time. Turning it off makes generation effectively instant and is the right default for a batch job or a preview. Turn it on for the copy that goes to the customer.
The asset object#
Nameplate fields, then test blocks. Every block is optional; a block you omit is a section the report does not print.
{
"job_name": "Cedar Ridge Substation - ATS",
"job_number": "2026-0418",
"client": "Cedar Ridge Utilities",
"technician": "D. Okafor",
"date": "2026-09-04",
"service_class": "acceptance", report names ANSI/NETA ATS-2021; "maintenance" names ANSI/NETA MTS-2023
"output_format": "pdf",
"report_depth": "standard",
"include_summary": false,
"assets": [{
"equipment_type": "LV Breaker",
"form_type": "lv_breaker", picks the renderer, prefer over equipment_type
"manufacturer": "Square D",
"model": "MasterPact NW20H",
"serial_number": "SD-2210-4471",
"asset_id": "52-1",
"location": "SWGR-1",
"voltage_class": "480V",
"amp_rating": "2000A",
"interrupting_kA": "65",
"poles": "3",
"trip_unit": "Micrologic 6.0A",
"insulation": {
"ab_open": 5200, "bc_open": 4980, "ca_open": 5310, MΩ, breaker open
"ag_open": 6100, "bg_open": 5890, "cg_open": 6020, phase-to-ground
"a1a2": 4700, "b1b2": 4650, "c1c2": 4720, line-to-load, closed
"test_voltage_vdc": 1000,
"duration_min": 1.0,
"temperature_c": 24,
"humidity_pct": 41,
"instrument": "Megger MIT525"
},
"contact_resistance": { µΩ (DLRO)
"phase_a": 121, "phase_b": 118, "phase_c": 124,
"test_current_a": "100A DC",
"instrument": "Megger DLRO10HD"
},
"secondary_injection": {
"enabled": true,
"long_time": {
"enabled": true,
"setting_as_found": "0.9 × 2000A",
"setting_as_left": "0.9 × 2000A",
"current_applied": "300%",
"trip_time_a": 18.4, "trip_time_b": 18.1, "trip_time_c": 18.6,
"acceptable_range": "15–25 s",
"result": "PASS"
},
"short_time": { "enabled": false },
"instantaneous": { "enabled": false },
"ground_fault": { "enabled": false }
},
"hi_pot": { "enabled": false },
"visual_items": []
}]
}| Test block | Units | Shape |
|---|---|---|
insulation | MΩ | Six open readings, three line-to-load, plus ng_open for four-wire gear, and the test conditions. |
contact_resistance | µΩ | Three phases, test current and instrument. |
secondary_injection | s | Four trip elements (long_time, short_time, instantaneous, ground_fault) each with as-found/as-left settings and per-phase trip times. |
primary_injection | A, s | Pickup current, per-phase clearing times, CT ratio. |
hi_pot | kV, µA | Test voltage, leakage, duration, result. |
visual_items | - | Mechanical and visual inspection checklist rows. |
POST /reports/validate takes the same body and returns findings without generating anything. It is fast and free, and it catches the readings that will silently print as blank. Run it in CI against your mapping layer.
Response#
output_format | Content-Type |
|---|---|
pdf | application/pdf |
excel | application/vnd.openxmlformats-officedocument.spreadsheetml.sheet |
Generated documents are also retained and listable via GET /reports, so a client that lost the response can fetch it again rather than paying to render it twice.