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.






Proof that the IDs are in the file



How it was validated
"Valid" has four layers. The first three were run here; the fourth needs a second implementation.
| Layer | What it checks | Instrument | Result |
|---|---|---|---|
| 1. Part 21 syntax | The file parses and every reference resolves | NX's own importer; the tool's parser | pass 0 errors, 0 warnings on every output |
| 2. Schema | Every record against the AP242 edition 4 longform EXPRESS schema the rec prac names: entity exists, exact attribute count including the supertype chain, typed wrappers defined | validate_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 practice | Header 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, edges | validate_pids, ten checks, each with a corruption test that makes it fail | pass 10 of 10 on all three test parts |
| 4. Interoperability | A 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 PIDs | Not 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 exports | Persisted | Deleted | New | Retargeted |
|---|---|---|---|---|
| Expression p557, 12.7 → 14.0 mm | 3389 / 3389 | 0 | 0 | 0 |
| Expressions p556 and p558, 6.35 → 7.0 mm (48 points moved) | 3389 / 3389 | 0 | 0 | 0 |
| No change, straight re-export | 3389 / 3389 | 0 | 0 | 0 |
| 20 × 20 × 80 mm block cut through the web | 3389 / 3389 | 0 | 19 (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.