Collectors (Write)
Create Collector
POST /api/v1/collectors
Request body:
{
"name": "collector-1",
"description": "Primary collector",
"config": { ... },
"area_id": "uuid",
"enabled": true
}
Validation: name, config, and area_id are all required. When present in the config blob, config.snmp.target, config.gre.local_ip, and config.gre.remote_ip must each be a valid IP address, and config.discovery_mode must be one of gre, snmp, isis-gre, isis-snmp, eigrp-snmp (absent = GRE; bgpls is engine-managed and refused with its own message) — otherwise the request is rejected with 400. An isis-snmp config additionally requires config.hierarchy.area to be exactly level-2 or level-1:<canonical-area-address>; config.snmp.crawl_abrs=true is accepted only with level-2. Missing, generic (level-1), malformed, over-long, or non-canonical area values are rejected rather than starting an unscoped recorder. An eigrp-snmp config may carry config.eigrp.route_walk_interval_seconds: how often the routers' EIGRP topology and RIB tables are read for the devices this recorder covers. Absent or 0 inherits the network's discovery_interval_hours; any other value must be a whole number of minutes expressed in seconds (a multiple of 60) between 300 (five minutes) and 2678400 (31 days), and anything else — a negative, a fraction, a non-minute value such as 330, an overflowing magnitude, a string — is rejected rather than repaired or read as "inherit" — by this endpoint, by the collector-manager, and by the store reader the SNMP poller obeys, so a row imported around the API cannot poll on an unsupported cadence while its collector row reads error. The web form writes an explicit 3600-second value for a new EIGRP recorder; clearing that field or omitting the API property retains the inheritance contract, and editing an older recorder does not add the new UI default. The same number fixes the route-history freshness lease (2 × interval + 10 min). A configured override gets its own poll schedule rather than riding the counters tick, so it also applies where counter polling is disabled; changing it takes one immediate walk even while the poller is running (the recorder refresh wakes the target's own timer), and an on-demand discovery (POST /api/v1/snmp/discover-now) always reads the tables however long the interval. It overrides the network cadence in both directions and governs the route walk only — hierarchy and interface enrichment keep riding the network discovery pass. config.snmp.targets is a bootstrap seed list, not the recording scope: an EIGRP recorder records every device in its network, and an empty list is valid at create and on update (deleting a device prunes its address from it, and such a recorder must stay editable). enabled defaults to true when omitted; an explicit false creates the collector stopped.
Response: 201 Created
Error: 400 Bad Request — Missing required field (name, config, or area_id), an invalid IP in config.snmp.target / config.gre.local_ip / config.gre.remote_ip, or an invalid IS-IS SNMP home-area/crawler combination
Update Collector
PUT /api/v1/collectors/{collectorID}
Performs a partial merge-update (only fields provided are updated).
enabled only changes when explicitly present in the body — a config-only
update never starts or stops the collector. For backward compatibility on ordinary
collectors, name: null, name: "", and area_id: null are no-ops; a non-null
area_id, including the empty string, follows the historical update path and may still
fail database validation. A completed bootstrap child is stricter: supplying an empty or
null protected identity field is an attempted identity change and returns 400.
Request body: Same as create (all fields optional).
Response: 200 OK
Errors: 404 Not Found; 400 Bad Request when a completed bootstrap child attempts
identity/provenance drift; 409 Conflict while a child is still owned by an active
bootstrap parent.
Toggle Collector
POST /api/v1/collectors/{collectorID}/toggle
Flips the enabled flag and updates the status field ("pending" if enabled, "stopped" if disabled).
Response: 200 OK (updated collector object)
Errors: 404 Not Found; 409 Conflict while a child is still owned by an active
bootstrap parent.
Delete Collector
DELETE /api/v1/collectors/{collectorID}
Response: 204 No Content
Errors: 404 Not Found; 409 Conflict while a child is still owned by an active
bootstrap parent.