Persistent IDs for NX STEP export

An NX part becomes a STEP AP242 file that carries a CAx-IF Persistent ID on every PMI, face, edge and on the product. This page shows the interface inside NX that does it, the proof that the IDs are in the file, every layer of validation that was run, and the documentation. Everything here was produced on NX 2606 on 22 September 2026.

What a Persistent ID is

A Persistent ID (PID) is a UUID attached to an element of a STEP file so that the same element can be recognised in the next export of the model and by downstream consumers such as CAM, CMM and QIF tools. The rules are the CAx-IF Recommended Practice Persistent IDs for Design Iteration and Downstream Exchange v1.8 (March 2026): product and product version, every semantic PMI, every face and edge (never a vertex) get a UUID; the UUID goes into the Data Section as V5_UUID_ATTRIBUTE or V4_UUID_ATTRIBUTE with a UUID_SET_ITEM; V5 is preferred because it repeats, V4 is legal but must be labelled V4; and the header must carry CAx-IF Rec.Pracs.---Persistent IDs---1.8---2026-02-27.

NX 2606 writes none of this by itself. It does keep a native UUID on every PMI object (Annotations.Pmi.UniversallyUniqueId) and exports a face's or edge's name into the STEP entity name. The tool uses both: PMI UUIDs are read from NX, faces and edges are given a V5 UUID as their NX name, and the STEP file is completed with the UUID records after export.

The interface inside NX

A custom directory adds a PIDs menu to NX with five commands. Each one is an NX Open journal; the same code runs headless with run_journal.exe.

NX Menu with the PIDs submenu: Export STEP with PIDs, Show PIDs, Tag PIDs as attributes, Validate a STEP file, Import STEP with PIDs
Menu → PIDs in NX 2606 with the rib part open. Five commands: Export STEP with PIDs, Show PIDs, Tag PIDs as attributes, Validate a STEP file, Import STEP with PIDs.
Information window listing every PMI with its UUID
Show PIDs: the Information window lists every PMI of the open part with its index, type, text and NX UUID. NX's own Menu → Information → Object prints the same value for one PMI at a time.
Export STEP with PIDs result box: 3389 UUID records, validator pass
Export STEP with PIDs on the rib: 3,389 UUID records (66 PMI, 3,321 topology, 2 product), validator pass, each step reported. The part is saved with its PIDs so the next export repeats them.
NX file box for Validate a STEP file
Validate a STEP file opens NX's native file box.
Validate STEP result: PASS, 13 checks
The validation result: 13 checks pass, details in the Information window and a JSON report beside the file.
NX with the STEP file imported: MBD Navigator lists the dimensions by callout name
Import: the STEP file opened in NX 2606. The MBD Navigator lists the imported dimensions by the same callout names the UUID records key on. NX's importer drops the UUID records themselves; the Import STEP with PIDs command re-attaches them (see below).

Proof that the IDs are in the file

Table: NX PMI read-back next to the STEP record carrying each UUID, all match
Left: what NX reports through NXOpen for each PMI (index, type, text, UUID). Right: the record in the STEP file that carries that UUID and the semantic entity it points at. 66 of 66 match. The drawing is the rib the file was exported from.
Notepad showing the appended V4_UUID_ATTRIBUTE records
The STEP file in Notepad at the line where the appended block starts: product, version and PMI records.
Notepad showing V5_UUID_ATTRIBUTE records for faces and edges at the end of the file
The end of the same file: V5 records for faces and edges, 16 MB, 218,441 lines.

How it was validated

"Valid" has four layers. The first three were run here; the fourth needs a second implementation.

LayerWhat it checksInstrumentResult
1. Part 21 syntaxThe file parses and every reference resolvesNX's own importer; the tool's parserpass 0 errors, 0 warnings on every output
2. SchemaEvery record against the AP242 edition 4 longform EXPRESS schema the rec prac names: entity exists, exact attribute count including the supertype chain, typed wrappers definedvalidate_pids schema checks over the public ISO schema (2,407 entities)pass 58,039 records on the rib; also passes the file the CAx-IF validator accepted in April
3. Recommended practiceHeader string, V4/V5 subtypes only, UUID format and version nibble, references exist, allowed target types, no duplicates, no vertices, no id_attribute, coverage of product, PMI, faces, edgesvalidate_pids, ten checks, each with a corruption test that makes it failpass 10 of 10 on all three test parts
4. InteroperabilityA second implementation imports the file, keeps the UUIDs and recognises the same entities on the next iteration (the CAx-IF round-robin)An outside consumer that implements edition 4 PIDsNot run: NX 2606's importer is not such a consumer. Producing side proven (next section).

Known wart: NX declares AP242 edition 2 in the header while the UUID records are edition 4 entities. The CAx-IF gate accepted exactly this from NX in April 2026. WHERE rules and attribute types are not evaluated by the schema checks.

rib.validate.json (the 13 checks)
loading…
NX's own import log for the STEP file (round trip)
loading…

Design iteration on the rib

The rec prac's design-iteration case: edit the model, export again, and the untouched entities must keep their UUIDs. One copy of the rib, four exports, diffed with iteration_diff:

Edit between exportsPersistedDeletedNewRetargeted
Expression p557, 12.7 → 14.0 mm3389 / 3389000
Expressions p556 and p558, 6.35 → 7.0 mm (48 points moved)3389 / 3389000
No change, straight re-export3389 / 3389000
20 × 20 × 80 mm block cut through the web3389 / 3389019 (6 faces, 12 edges, 1 split)0

The web faces whose loops changed kept their UUIDs; only the new cut faces and edges got new ones. Faces deleted is not covered: suppressing any of this rib's extrudes makes NX roll the update back.

rib.iteration_diff_run5.json (the block cut)
loading…

Importing the STEP file back with its PIDs

NX's AP242 importer drops the UUID records silently but keeps face and edge names and the PMI callout names. import_with_pids imports the file and re-attaches every UUID it can join: PMI by callout name, faces and edges by name, product and version on the part, as a PID_UUID attribute. On the rib: 66 of 66 PMI, 1,024 of 1,024 faces, 2,296 of 2,296 edges, product and version. The native PMI UUID is read-only through NXOpen, so on the imported side it lives as an attribute.

rib.import_pids.json
loading…

Documentation

The two documents that ship with the tool, verbatim. Also: the proof page (searchable HTML), the PID map for the rib (every UUID, its STEP entity and its NX object).

README.md
loading…
SKILL.md (the recipe as recorded for future sessions)
loading…

Get it

Repository: github.com/chrisdamonmartini/nx-step-pid (private).

git clone https://github.com/chrisdamonmartini/nx-step-pid
cd nx-step-pid
python -m nxpid.fetch_schema                       # AP242 ed4 schema for the validator, once
powershell nxgui\Install-NxPidGui.ps1              # PIDs menu appears in NX on next start

# headless, one journal, whole run:
"C:\Program Files\Siemens\Designcenter2606\NXBIN\run_journal.exe" nxpid\journal_all_in_one.py -args part.prt out_dir

Tested on NX 2606.5001 (Designcenter) with three parts: a Siemens/NG PID test part (39 PMI), a Creo file imported into NX (no PMI), and a DXF-recovered rib (66 PMI, 1,024 faces, 2,296 edges). 42 tests, each validator check driven to fail by its own corruption.