Device Facts API
External validation tools write boolean and other scalar facts onto a device through this endpoint. It is the phase-1 ingress for OpenText Network Automation (NCO), which already performs configuration validation and needs only to report the result back to ServiceRadar.
Composite service checks consume these facts as device_metadata inputs, so a
fact written here can take part in a verdict such as "isolation is observed AND
the access-control configuration that enforces it is applied". After writing
facts, kick a targeted re-probe and read that verdict through
Composite Check Validation Runs. That page also
covers rolling the API into production (UAL): there is no new Helm value;
roll core-elx and web-ng on the usual global.imageTag.
Endpoint
PATCH /api/devices/:uid/metadata
Request body:
{
"facts": {
"nac_applied": true
}
}
Response:
{
"data": {
"uid": "sr:9f0c...",
"facts": {
"nac_applied": {
"value": true,
"source": "nco-service-account",
"updated_at": "2026-08-12T15:04:05.123456Z"
}
}
}
}
Only externally written facts are echoed back, not the device's whole metadata map.
Authorization
The caller needs the devices.facts.write permission. It is deliberately
separate from devices.update: a validation tool should be able to set a
boolean without also being able to rename, retag, or reassign the device. Grant
it to a dedicated service account rather than reusing an operator login.
What you can write
- Keys must match
^[a-z][a-z0-9_]{0,63}$. - Values must be scalars: boolean, number, or string.
- At most 32 externally written facts per device. Overwriting a fact you already wrote does not count against the cap.
- Keys reserved for internal enrichment are rejected, including
passive_fingerprint,identity_state,identity_source, and__fact_provenance.
If any fact in a request is invalid, the whole request is rejected and nothing is written. A partial write would leave the caller believing every fact landed.
Provenance and freshness
Alongside the plain value, the server records who wrote the fact and when,
under the __fact_provenance metadata key. This is stamped server-side; a
timestamp supplied in the request body is ignored, so a fact cannot be
back-dated.
This matters for composite checks. A device_metadata input may declare a
max_age, and a fact older than that resolves as unknown rather than as its
stored value — which normally sends the device's verdict to inconclusive.
Consequence for the integration: NCO must re-write a fact at least once per
configured max_age window even when the value has not changed. A fact written
once and never refreshed will age out and stop contributing to verdicts.
If an input declares no max_age, the stored value is used regardless of age
and no provenance is required. That keeps metadata keys written by paths which
do not record provenance usable as inputs.
Errors
| Status | Meaning |
|---|---|
| 400 | facts missing, empty, or not an object |
| 403 | caller lacks devices.facts.write |
| 404 | no device with that uid |
| 422 | a fact violated the key pattern, value type, reserved-key list, or the per-device cap |
Phase 2
This endpoint is the interim path. The longer-term ingress is the signed
OpenText Network Automation Wasm plugin described in
add-external-inventory-wasm-plugin-contract, which lands the same signal as
bounded source_metadata on device source observations. When that arrives the
device_metadata composite input gains a source: option, and existing
authored checks continue to work unchanged.