Skip to content
Documentation Prelude Collector 1.0.0

Workflow

End-to-end API workflow for creating, testing, and subscribing to a data model in Prelude Collector — request and response shapes for every step.

This page walks through the API calls to take a model from "doesn't exist yet" to "actively collecting data". After this first mention, the rest of this page refers to Prelude Collector as "the collector". Models are stored in the database, loaded into the collection engine at startup, and hot-reloaded within ~500 ms of any change to their fields or mappings — active subscriptions are re-configured automatically without a restart.

This page is the data-shape reference. For a narrative walk-through of building a multi-vendor model, see the interface counters tutorial.

End-to-end data shape

A complete, ready-to-use custom model goes through five API steps:

  1. Create the model definition.
  2. Add typed fields.
  3. Add one or more protocol mappings.
  4. Run a live collection test against a real device.
  5. Create a subscription to start continuous collection.

The rest of this page documents the request and response shapes for each step. For the exact endpoint paths and full schemas, see the API reference.

Step 1 — Create the model

export BASE="https://collector.example.com"
export TOKEN="<your-api-token>"

curl -s -X POST "$BASE/api/v1/models" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "my-bgp-summary",
    "description": "BGP summary table via SNMP",
    "version": "1.0"
  }'

Bruno: 04 Models / Create model

UI: https://collector.example.com/models/new

Validation rules:

  • name is required, max 100 characters, and must match ^[a-zA-Z0-9][a-zA-Z0-9._-]*$.
  • name must be globally unique (case-insensitive).
  • description max 500 characters.

Response 201 Created:

{
  "id": 7,
  "name": "my-bgp-summary",
  "description": "BGP summary table via SNMP",
  "version": "1.0",
  "is-active": true,
  "fields": [],
  "mappings": []
}

You can also inline fields in the create body. The API validates each field's type and format before saving.

Step 2 — Add fields

curl -s -X POST "$BASE/api/v1/models/7/fields" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "neighbor-address",
    "field-type": "string",
    "format": "ip-address",
    "required": true,
    "description": "BGP neighbor IP (row key)",
    "position": 0
  }'

Bruno: 04 Models / Add field

UI: https://collector.example.com/models/7

Repeat for each field. The supported field-type values are:

string   int32   int64   uint32   uint64   float32   float64   boolean

To change the display order after adding all fields, send an array of field IDs in the desired order to the reorder endpoint:

curl -s -X POST "$BASE/api/v1/models/7/fields/reorder" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '[12, 10, 11, 13]'

Bruno: 04 Models / Reorder fields

The engine assigns position values from the array index. For the update and delete endpoints, see the API reference.

Step 3 — Add a protocol mapping

curl -s -X POST "$BASE/api/v1/models/7/mappings" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "protocol": "snmp",
    "netos": "ios-xr",
    "key-field": "neighbor-address",
    "snmp-walk-oids": ["1.3.6.1.2.1.15.3"],
    "field-mappings": {
      "bgpPeerRemoteAddr": "neighbor-address",
      "bgpPeerState":      "session-state",
      "bgpPeerRemoteAs":   "peer-as"
    },
    "value-transforms": {
      "session-state": {
        "1": "idle",
        "2": "connect",
        "3": "active",
        "4": "opensent",
        "5": "openconfirm",
        "6": "established"
      }
    }
  }'

Bruno: 04 Models / Add mapping

UI: https://collector.example.com/models/7/mappings/new

Protocol-specific path fields

Use exactly one set of path fields for the chosen protocol:

Protocol Path fields
gnmi gnmi-paths (array), optional gnmi-path-filter
snmp snmp-walk-oids and / or snmp-scalar-oids
netconf netconf-filter-paths (array of XML subtree filter strings)
cli cli-commands (array, may use {param} placeholders), cli-template (TTP template), cli-discovery-params

Version constraints

To target a specific firmware range, add version-constraints:

{
  "protocol": "gnmi",
  "netos": "ios-xr",
  "version-constraints": [">=7.5", "<8.0"],
  "key-field": "neighbor-address"
}

The engine picks the matching mapping with the highest specificity (most constraints) for the device's reported version. If two equally-specific mappings match, both are skipped and an error is recorded.

Uniqueness constraint

The combination (model, protocol, netos, version-constraints) must be unique. Adding a second mapping with the same protocol, NetOS, and version constraints returns 409 Conflict.

Path syntax warnings

After saving a mapping, the API may include a warnings array on the response if it detects path syntax issues — for example, an invalid gNMI path format. These are non-blocking; the mapping is saved regardless.

{
  "id": 3,
  "protocol": "gnmi",
  "warnings": ["gnmi-paths[0]: path does not begin with a module prefix"]
}

Step 4 — Run a live collection test

Before subscribing, validate the model against a real device:

curl -s -X POST "$BASE/api/v1/models/7/test" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "device-id": 3,
    "mapping-id": 5
  }'

Bruno: 04 Models / Test mapping

UI: https://collector.example.com/models/7/test

The engine connects to the device using the protocol configured for the mapping and collects data for up to 8 seconds, returning early once 1.5 seconds elapse with no new updates (the initial burst has settled).

Response 200 OK:

{
  "device": "router-core-01",
  "protocol": "snmp",
  "raw-data-received": true,
  "results": [
    {
      "key": "192.0.2.1",
      "model-name": "my-bgp-summary",
      "data": {
        "neighbor-address": "192.0.2.1",
        "session-state": "established",
        "peer-as": 65001
      }
    }
  ],
  "raw-updates": []
}
  • results contains parsed, field-mapped data.
  • raw-updates shows the raw protocol output before any mapping is applied — useful when debugging field-mapping keys.

Tip

If raw-data-received is true but results is empty, the parser received data but could not extract the key field. Check that key-field matches an actual leaf name in raw-updates.

Step 5 — Create a subscription

Once the test passes, activate the model on a device:

curl -s -X POST "$BASE/api/v1/subscriptions" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "device-id": 3,
    "model-name": "my-bgp-summary",
    "protocol": "snmp",
    "interval": 60
  }'

Bruno: 05 Subscriptions / Create subscription

UI: https://collector.example.com/subscriptions/new

device-id, model-name, and protocol are required. The collector defaults interval to 60 seconds and forces enabled to true on creation; the new subscription starts in the stopped status and transitions on its first poll. The collection engine resolves the correct mapping at each poll cycle based on the device's NetOS and firmware version.

Import / export format

Models can be exported and imported as self-contained JSON files, which makes it easy to move a working model between environments or to seed a starter catalogue.

Export

curl -s -X GET "$BASE/api/v1/models/7/export" \
  -H "Authorization: Bearer $TOKEN" \
  -o my-bgp-summary.json

Bruno: 04 Models / Export model

UI: https://collector.example.com/models/7

The response is a JSON document with Content-Disposition: attachment.

Import

curl -s -X POST "$BASE/api/v1/models/0/import" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  --data-binary @my-bgp-summary.json

Bruno: 04 Models / Import model

UI: https://collector.example.com/models

The path takes a model ID for routing consistency but the import handler ignores it — every imported model is created from the JSON body. Import fails with 400 if a model with the same name already exists.

Export schema

{
  "name": "my-bgp-summary",
  "description": "BGP summary table via SNMP",
  "version": "1.0",
  "fields": [
    {
      "name": "neighbor-address",
      "field-type": "string",
      "format": "ip-address",
      "required": true,
      "description": "BGP neighbor IP (row key)",
      "position": 0
    },
    {
      "name": "session-state",
      "field-type": "string",
      "required": false,
      "description": "BGP session state",
      "position": 1
    }
  ],
  "mappings": [
    {
      "protocol": "snmp",
      "netos": "ios-xr",
      "version-constraints": [],
      "key-field": "neighbor-address",
      "snmp-walk-oids": ["1.3.6.1.2.1.15.3"],
      "field-mappings": {
        "bgpPeerRemoteAddr": "neighbor-address",
        "bgpPeerState":      "session-state"
      },
      "value-transforms": {
        "session-state": {
          "6": "established"
        }
      }
    }
  ]
}

All array and map fields (version-constraints, gnmi-paths, field-mappings, field-transforms, value-transforms, ignore-values, cli-discovery-params) are optional and are omitted when empty.

Hot-reload behaviour

After any field or mapping change (create, update, delete), the collector debounces the event and fires a reload ~500 ms after the last change. The reload:

  1. Re-reads the model from the database.
  2. Rebuilds the in-memory model registry.
  3. Re-subscribes every active device collector that uses the model with the new configuration.

If you delete the model or set is-active to false, it is removed from the registry immediately and all associated collectors are torn down.

See also

Filtering by: