Skip to content

V1 field names — API v2

Existing integrations usually address calServer by its V1 field names, the METTRACK codes such as C2301 or I4201. V2 gives those same fields readable names (calibration_date, asset_number) — and the V1 codes stay valid identifiers. A tool written against V1 does not have to change its field names.

What works out of the box

Filtering, sorting and writing accept the V1 code anywhere the readable name is accepted:

# Both requests return the same rows
curl "…/api/v2/calibrations?filter[calibration_date]=2025-03-15" -H "$AUTH"
curl "…/api/v2/calibrations?filter[C2301]=2025-03-15"            -H "$AUTH"

# Sorting likewise
curl "…/api/v2/calibrations?sort=-C2301" -H "$AUTH"

# Writing likewise
curl -X PUT "…/api/v2/calibrations/{id}" -H "$AUTH" \
  -H "Content-Type: application/json" \
  -d '{"C2307": "M. Mustermann"}'

If a request carries both spellings of the same field, the readable name wins — so a client that already migrated does not overwrite its own values with a legacy key left behind in the code.

What you have to switch on: V1 names in the response

By default responses carry each field under its readable name only. Shipping every field twice would add some seventy keys to an inventory row, including for clients that never need them. Ask for the codes when you want to read them:

curl "…/api/v2/calibrations?include_v1_names=1" -H "$AUTH"
curl "…/api/v2/calibrations" -H "$AUTH" \
  -H "X-CalServer-V1-Field-Names: 1"

The codes are added alongside the readable names, never instead of them:

{
  "data": [
    {
      "id": "…",
      "type": "calibration",
      "attributes": {
        "calibration_date": "2025-03-15",
        "C2301": "2025-03-15",
        "technician": "M. Mustermann",
        "C2307": "M. Mustermann"
      }
    }
  ]
}

The header is for clients that cannot change their URLs; the query parameter is for everything else. Both apply to lists and single reads.

Limits

A V1 code is not resolved when it does not point at exactly one field. That covers three cases, and in each the alternative would be to guess a mapping — which is how a tool ends up writing to the wrong field:

  • The code is also the readable name of a different field on the same table. The real field wins.
  • Several fields on the same table claim the same code.
  • The field has no V1 code recorded — for instance a field that never existed in V1.

In those cases only the readable name works.

Primary keys are not registry fields

A table's own key is not part of the field management, so there is no code to resolve for it: filter[MTAG] on /api/v2/inventories and filter[CTAG] on /api/v2/calibrations are discarded and therefore return every record instead of an error. Use filter[id]=…, or the path /api/v2/inventories/{mtag}. As a foreign key the same code does work (filter[MTAG] on /api/v2/calibrations hits inventory_id). Full detail with examples: IDs: MTAG, CTAG and the other tags. A field's code is shown in the

field management UI and in the API's field definitions (GET /api/v2/field-definitions/{table}, attribute v1_name).

Installations that use V1 names

Many installations are set up so the V1 code is the api_name — there the normal response already carries the codes and the switch above changes nothing. GET /api/v2/field-definitions/{table} shows which variant you have: api_name and v1_name sit next to each other.