Skip to content

The setup file (JSON) ​

A parsing setup can be downloaded as a JSON file and uploaded back. The file holds every rule of the setup, so it is how you move a setup between companies, keep a copy outside the platform, or write a setup somewhere else and bring it in finished.

This page is the reference for that file: every field, every key, and what a value has to look like for the platform to read it.

You do not have to write it by hand

Claude can write the whole file for you from a sample IFC and a description of your panels. See Let Claude write it at the end of this page.

Download and upload ​

Both live in Projects Settings → IFC Parsing Setups, in the company menu under Settings.

ActionWhereWhat it does
DownloadThe ↓ button on a setup rowSaves ifcps_<name>.json. The uuid and the company are stripped, so the file describes rules and nothing else.
UploadUPLOAD in the toolbarReads the file and opens the editor filled in with it.

Uploading saves nothing on its own. The file lands in the normal editor, you check it tab by tab, and it exists only when you press Save.

A uuid in the file overwrites that setup

A downloaded file carries no uuid, so uploading it always creates a new setup. If you add a uuid by hand, saving overwrites the setup with that uuid and re-analyses every project using it. Leave it out.

The two building blocks ​

Almost every value in the file is one of two things.

A rule ​

Used by the categories, the assembly filter, the machine flags, the branches and the classes. Three keys:

json
{ "prop_key": "reference", "match": "prefix", "value": "TR" }
{ "prop_key": "reference", "match": "prefix", "value": "TR" }
KeyValue
prop_keyThe property to look into. Any property name the file carries, or one of the five element attributes below. Case does not matter.
match"all", "prefix" or "contains".
valueWhat to look for. Case does not matter.
matchMatches when the property value
allis exactly this value
prefixstarts with this value
containsholds this value anywhere

A part matches a setting when any one of its rules matches. A rule whose prop_key the element does not carry never matches, and neither does one whose match is missing or misspelled.

Never leave value empty

An empty value with match set to prefix or contains matches every element that carries the property, because every string starts with nothing and holds nothing. A whole category would swallow the panel.

The editor refuses to save a rule with an empty value, so an uploaded file is caught before it does any harm — but it is caught as a red field on some tab you have to go and find. Do not write one.

The five element attributes are always available as prop_key, whatever the file's property sets are called:

name · ifc_tag · ifc_id · object_type · description

Everything else has to be a property the exporter actually wrote: reference, zone, profile and the rest are only useful if your IFC carries a property with that name.

A property name list ​

Used by everything under props, steel_props and project_props. Here you do not match, you say where to read a value from: a list of property names, tried in order, first one present on the element wins.

json
"weight": ["WEIGHT", "GEWICHT"]
"weight": ["WEIGHT", "GEWICHT"]

Reading from one property set only ​

Both blocks take an optional pset, for the case where two property sets carry the same property name with different values.

json
{ "prop_key": "reference", "match": "prefix", "value": "TR", "pset": "Tekla_Common" }
{ "key": "ZONE", "pset": "Pset_WallCommon" }
{ "prop_key": "reference", "match": "prefix", "value": "TR", "pset": "Tekla_Common" }
{ "key": "ZONE", "pset": "Pset_WallCommon" }
psetWhat is read
absentThe property wherever it appears. The normal case.
"Tekla_Common"That property set only.
""The element's own attributes only.

A property name list takes the plain string form "ZONE" or the scoped form {"key": "ZONE", "pset": "..."}, and you can mix both in the same list.

The editor offers pset on the category, filter and flag rules and on the property names. It is not offered on the entries of custom_branches and part_classes, so leave it out there.

BTLx files have no property sets

The same setup reads BTLx files, where prop_key is the name of an attribute on the BTLx part (Designation, Material, Group). A scoped entry never matches a BTLx part.

Top-level fields ​

json
{
  "name": "Tekla Wall Panels",
  "is_default": false,
  "setup": {},
  "props": {},
  "steel_setup": {},
  "steel_props": {},
  "project_setup": {},
  "project_props": {},
  "level_setup": {},
  "custom_branches": [],
  "part_classes": []
}
{
  "name": "Tekla Wall Panels",
  "is_default": false,
  "setup": {},
  "props": {},
  "steel_setup": {},
  "steel_props": {},
  "project_setup": {},
  "project_props": {},
  "level_setup": {},
  "custom_branches": [],
  "part_classes": []
}
FieldTypeHolds
namestring, max 22 charactersThe setup name. Required.
is_defaultbooleanWhether new projects start from this setup. Only one setup per company can be the default.
setupobjectPanel part categories, operations and machine flags. Rule lists.
propsobjectPart properties. Property name lists.
steel_setupobjectSteel cage categories. Rule lists.
steel_propsobjectSteel cage properties. Property name lists.
project_setupobjectThe assembly filter. Rule lists.
project_propsobjectWhat is read off a module or an assembly. Property name lists.
level_setupobjectHow the file is split into levels, plus the BTLx zone rules.
custom_branchesarrayYour own kinds of part.
part_classesarrayYour own classes and their behaviours.

Every one of them may be left out, and an empty object or list is valid. A category with no rules simply recognises nothing.

Fields you can ignore

wood_setup, wood_props, concrete_setup, concrete_props, custom_setup, custom_props and level_props exist in the file for compatibility. The editor writes to none of them. Leave them out.

read_only and company_lock are locks, not rules. Leave them out too.

setup — categories, operations and flags ​

Every key holds a list of rules.

A mistyped key here is not ignored

The rules under it still run, and a part matching one is filed under a category nothing recognises: it drops out of the parts list, the measurements, the reports and the machine files without a word. It can also outrank a correct rule and take a part away from the category it belonged in.

Check every key against the tables below. This is the single most common way a hand-written setup goes wrong.

Frame ​

KeyWhat it is
top_railThe horizontal wood at the top of the frame
bottom_railThe horizontal wood at the bottom
extra_top_railWoods over the top rail
extra_bottom_railWoods below the bottom rail
woodAny other frame wood: studs, noggins, diagonals
extra_woodFrame woods outside the standard framing
battenBattens fixed on the panel

Plates ​

KeyWhat it is
plateA sheet on a face of the frame
core_plateA plate inside the frame

Other parts ​

KeyWhat it is
brickSingle bricks or stones
openingDoor and window placeholders, not produced

Areas and flags ​

KeyWhat it is
lockout_areaAreas the machine must not work on
isolated_areaAreas that carry insulation
skip_framing_woodBTLx parts that must not be counted as framing wood

Operation lines ​

KeyWhat it is
frame_nailFrame nail lines
frame_nail_singleSingle frame nails
plate_nailPlate nail lines
plate_screwPlate screws
glueGlue lines
glue_areaGlue areas

Cutting and milling ​

KeyWhat it is
frame_sawSaw cuts on the frame
frame_drillDrills on the frame
millingMilling lines
sawingSawing lines on the plates
drillingDrilling operations

Machine flags (BTLx) ​

Each one mirrors a property of the same job under props, for files that carry attributes instead of properties.

KeyWhat it is
brick_machine_flagBricks built by the machine
isolation_machine_flagInsulation applied by the machine
battens_machine_flagBattens fitted by the machine
v_millMilling lines done as a V-mill

Two keys that used to live here

ignore_me and hidden_material were categories and are now class behaviours — skip_everything and hide_in_viewer on a part class. A setup written today should use the classes; old files keep working. not_isolated_area was never read by anything.

props — part properties ​

Every key holds a list of property names. Unlike setup, a key that is not in this table is read by nothing — silently, so the property simply comes out empty and nothing says why.

KeyWhat it reads
nameThe part name. Left out, the element's own Name is used.
fab_refThe reference, expected to be the same for parts of the same shape
materialThe material name
shaped_section_nameThe profile name, for sections that are not rectangular
profile_joinedWhether the profile is extended or joined
zoneThe panel layer the part belongs to
finishThe finish
commentA free comment
weightThe weight in kg
volumeThe volume in m³
isolation_orderThe order insulation areas are filled in
nail_ctcCentre-to-centre distance in nail and screw lines
mill_depthDepth of a milling or sawing line
nail_tool_idThe tool the MOB2 machine nails with
frame_saw_sideThe side of the frame the saw works on
brick_typeThe type of brick
is_machine_brickBricks built by the machine
is_machine_isolationInsulation applied by the machine
is_machine_battensBattens fitted by the machine
is_vmillMilling lines done as a V-mill
skip_framing_woodParts not to be counted as framing wood

The zone reads a letter as a sign

A zone value holding a B becomes a negative zone; anything else stays positive, and letters are stripped. So F1 is 1 and B2 is -2.

That rule applies to every numeric property, so keep a B out of the values you map to nail_ctc, mill_depth, isolation_order and nail_tool_id.

steel_setup and steel_props ​

Only for the steel cage flow. Leave both out if you do not produce steel cages.

steel_setup keyWhat it is
top_steel_railTop steel profile
bottom_steel_railBottom steel profile
steel_profileAny other steel profile
steel_plateSteel plate
steel_welding_seamWelding seam
steel_props keyWhat it reads
steel_compute_holesWhether the holes of the profile are computed
assembly_idAssembly id, level 1
assembly_id2Assembly id, level 2

project_props — read off a module or an assembly ​

Property name lists, read off the container, not off its parts.

KeyWhat it reads
module_design_nameThe module design name. Instances of the same design share it.
custom_module_idThe unique id of each module instance
assembly_design_nameThe panel name. Left out, the container's own name is used.
custom_assembly_idThe unique id of each panel instance, such as the element number the customer uses. Stored on each assembly unit as its unit ID.
phase_nameThe phase a panel belongs to
batch_nameThe batch a panel belongs to
client_metaProperties copied onto the design as client data

project_setup — the module and assembly filters ​

Four rule lists deciding which modules and assemblies are split out of the project file. The split always takes out every level; these lists leave things out.

json
"project_setup": {
  "module_filter":       [],
  "module_filter_out":   [{"prop_key": "name", "match": "prefix", "value": "TEST"}],
  "assembly_filter":     [{"prop_key": "ASSEMBLY_PREFIX", "match": "prefix", "value": "WA"}],
  "assembly_filter_out": [{"prop_key": "name", "match": "contains", "value": "_TEST"}]
}
"project_setup": {
  "module_filter":       [],
  "module_filter_out":   [{"prop_key": "name", "match": "prefix", "value": "TEST"}],
  "assembly_filter":     [{"prop_key": "ASSEMBLY_PREFIX", "match": "prefix", "value": "WA"}],
  "assembly_filter_out": [{"prop_key": "name", "match": "contains", "value": "_TEST"}]
}
KeyMeaning
module_filterEmpty or absent, every module is split out as a module IFC. With rules, only matching modules are.
module_filter_outMatching modules are never split out, even when the first list keeps them.
assembly_filterEmpty or absent, every assembly is split. With rules, only matching assemblies are split.
assembly_filter_outMatching assemblies are never split, even when the first list keeps them.

In each pair the drop list always wins. An assembly that is not split produces nothing: no IFC file, no design, no row in the phase and batch counts. A module that is not split gives no module IFC and no module design; its assemblies are still split, as the assembly lists say. A module rule reads the module's name under name, and the properties of its first assembly.

level_setup — how the file is split ​

Three levels, each an object rather than a list of rules.

json
"level_setup": {
  "module":      { "detection": "ifc_class", "match": "IfcElementAssembly" },
  "assembly":    { "detection": "ifc_class", "match": "IfcElementAssembly" },
  "subassembly": { "detection": "part_prop", "match": "SUBASSEMBLY" }
}
"level_setup": {
  "module":      { "detection": "ifc_class", "match": "IfcElementAssembly" },
  "assembly":    { "detection": "ifc_class", "match": "IfcElementAssembly" },
  "subassembly": { "detection": "part_prop", "match": "SUBASSEMBLY" }
}
detectionmatch is
ifc_classAn IFC class name: IfcElementAssembly, IfcWall, IfcSlab, IfcPresentationLayerAssignment
part_propA property name read off the parts
ass_propA property name read off the assembly

On the subassembly level, ifc_class and ass_prop read the group a part sits in, and only when that group is inside the panel: a part straight in the panel belongs to the panel. For ifc_class, match is optional and narrows the groups to one class. See Subassemblies.

The same object also holds two more keys, each a plain list of rules, because BTLx layer numbers carry no sign and the face of the panel has to be declared.

KeyWhat it is
positive_zoneBTLx layers on the reference face of the panel
negative_zoneBTLx layers on the opposite face
json
"positive_zone": [{"prop_key": "Layer", "match": "all", "value": "1"}],
"negative_zone": [{"prop_key": "Layer", "match": "all", "value": "2"}]
"positive_zone": [{"prop_key": "Layer", "match": "all", "value": "1"}],
"negative_zone": [{"prop_key": "Layer", "match": "all", "value": "2"}]

They do nothing for IFC files, where the zone sign comes from the zone property instead.

custom_branches ​

Kinds of part beyond the built-in timber and plate: windows, connectors, airtightness, electrical, plumbing.

json
"custom_branches": [
  {
    "name": "windows",
    "alike": "generic",
    "logistics": true,
    "metrics": true,
    "entries": [{"prop_key": "reference", "match": "prefix", "value": "WIN"}]
  }
]
"custom_branches": [
  {
    "name": "windows",
    "alike": "generic",
    "logistics": true,
    "metrics": true,
    "entries": [{"prop_key": "reference", "match": "prefix", "value": "WIN"}]
  }
]
KeyValue
nameThe branch name. Lowercased everywhere it is used.
alike"generic", "plate" or "wood" — the geometry it resembles, so drawings and cutting lists know how to treat it.
logisticstrue puts its parts in the parts list and through logistics. Default false.
metricstrue counts its parts in the panel width, height, thickness and surface. Default false.
entriesThe rules that recognise it.

metrics is off by default and that has consequences

A branch is recognised before a part falls back to timber or plate from its category, so a part your setup knows perfectly well can end up with no category — and a part with no category is outside every panel measurement.

Turn metrics on for cladding and window frames. Leave it off for brackets and anything that sticks out past the frame.

part_classes ​

A category says what a part is. A class says how your factory treats it. A part can match several classes. Its name is the first class in the list whose rules match, so put the more specific classes first. Its behaviours add up from every class it matches.

json
"part_classes": [
  {
    "name": "Placeholder",
    "entries": [{"prop_key": "name", "match": "prefix", "value": "PLH"}],
    "behaviours": {"skip_area": true, "skip_x": true, "skip_y": true}
  }
]
"part_classes": [
  {
    "name": "Placeholder",
    "entries": [{"prop_key": "name", "match": "prefix", "value": "PLH"}],
    "behaviours": {"skip_area": true, "skip_x": true, "skip_y": true}
  }
]
KeyValue
nameThe class name. Settings that behave differently per kind of part, the framing nail matrix first, look it up by this.
entriesThe rules that recognise it.
behavioursOptional. Absent means the part behaves normally.
BehaviourWhat it does
skip_areaThe part is left out of the net, gross and opening areas
skip_xLeft out of the panel width
skip_yLeft out of the panel height
skip_zLeft out of the panel thickness
skip_everythingThe part is ignored completely: no parts list, no reports, no machine files
hide_in_viewerStill measured and still produced, only not drawn in the 3D viewer

All of them are false when absent, and false means the part counts. Only the keys you turn on need to be in the file.

The placeholder case

A layer that is not produced but takes up the space a real one will: it has to count for the thickness, because the panel really is that thick, and not for the surface, because nothing was produced. Turn on skip_area, skip_x and skip_y, and leave skip_z off. That is the example above.

A complete example ​

A small but working setup. Every field it leaves out is simply not used.

json
{
  "name": "Tekla Wall Panels",
  "level_setup": {
    "module":   { "detection": "ifc_class", "match": "IfcElementAssembly" },
    "assembly": { "detection": "ifc_class", "match": "IfcElementAssembly" }
  },
  "project_props": {
    "assembly_design_name": ["ASSEMBLY_NAME"],
    "phase_name": ["PHASE"],
    "batch_name": ["BATCH"]
  },
  "project_setup": {
    "assembly_filter_out": [
      { "prop_key": "name", "match": "contains", "value": "_TEST" }
    ]
  },
  "setup": {
    "top_rail": [
      { "prop_key": "reference", "match": "all", "value": "TOPRAIL" },
      { "prop_key": "reference", "match": "prefix", "value": "TR" }
    ],
    "bottom_rail": [
      { "prop_key": "reference", "match": "prefix", "value": "BR" }
    ],
    "wood": [
      { "prop_key": "reference", "match": "prefix", "value": "W" }
    ],
    "plate": [
      { "prop_key": "reference", "match": "prefix", "value": "P" }
    ],
    "opening": [
      { "prop_key": "name", "match": "contains", "value": "OPENING" }
    ],
    "frame_nail": [
      { "prop_key": "name", "match": "prefix", "value": "FNL" }
    ]
  },
  "props": {
    "fab_ref": ["REFERENCE"],
    "zone": ["ZONE", "LAYER"],
    "material": ["MATERIAL"],
    "weight": ["WEIGHT", "GEWICHT"],
    "volume": ["VOLUME", "NETVOLUME"],
    "nail_ctc": ["NAIL_CTC", "SCREW_CTC"]
  },
  "custom_branches": [
    {
      "name": "windows",
      "alike": "generic",
      "logistics": true,
      "metrics": true,
      "entries": [
        { "prop_key": "reference", "match": "prefix", "value": "WIN" }
      ]
    }
  ],
  "part_classes": [
    {
      "name": "Placeholder",
      "entries": [
        { "prop_key": "name", "match": "prefix", "value": "PLH" }
      ],
      "behaviours": { "skip_area": true, "skip_x": true, "skip_y": true }
    }
  ]
}
{
  "name": "Tekla Wall Panels",
  "level_setup": {
    "module":   { "detection": "ifc_class", "match": "IfcElementAssembly" },
    "assembly": { "detection": "ifc_class", "match": "IfcElementAssembly" }
  },
  "project_props": {
    "assembly_design_name": ["ASSEMBLY_NAME"],
    "phase_name": ["PHASE"],
    "batch_name": ["BATCH"]
  },
  "project_setup": {
    "assembly_filter_out": [
      { "prop_key": "name", "match": "contains", "value": "_TEST" }
    ]
  },
  "setup": {
    "top_rail": [
      { "prop_key": "reference", "match": "all", "value": "TOPRAIL" },
      { "prop_key": "reference", "match": "prefix", "value": "TR" }
    ],
    "bottom_rail": [
      { "prop_key": "reference", "match": "prefix", "value": "BR" }
    ],
    "wood": [
      { "prop_key": "reference", "match": "prefix", "value": "W" }
    ],
    "plate": [
      { "prop_key": "reference", "match": "prefix", "value": "P" }
    ],
    "opening": [
      { "prop_key": "name", "match": "contains", "value": "OPENING" }
    ],
    "frame_nail": [
      { "prop_key": "name", "match": "prefix", "value": "FNL" }
    ]
  },
  "props": {
    "fab_ref": ["REFERENCE"],
    "zone": ["ZONE", "LAYER"],
    "material": ["MATERIAL"],
    "weight": ["WEIGHT", "GEWICHT"],
    "volume": ["VOLUME", "NETVOLUME"],
    "nail_ctc": ["NAIL_CTC", "SCREW_CTC"]
  },
  "custom_branches": [
    {
      "name": "windows",
      "alike": "generic",
      "logistics": true,
      "metrics": true,
      "entries": [
        { "prop_key": "reference", "match": "prefix", "value": "WIN" }
      ]
    }
  ],
  "part_classes": [
    {
      "name": "Placeholder",
      "entries": [
        { "prop_key": "name", "match": "prefix", "value": "PLH" }
      ],
      "behaviours": { "skip_area": true, "skip_x": true, "skip_y": true }
    }
  ]
}

Before you upload ​

  • name is present and 22 characters or fewer.
  • There is no uuid.
  • Every key is one from the tables above. A mistyped key under props is read by nothing; a mistyped key under setup is worse, because its rules still run.
  • Every rule has all three of prop_key, match and value, and match is one of all, prefix, contains. A misspelled match never matches anything.
  • No rule has an empty value. The editor refuses to save one, and with prefix or contains it would have matched everything.
  • Every prop_key and every property name is a property your IFC really carries. This is the one thing the file cannot tell you: check it against a sample file.

After uploading, walk the tabs before saving. The editor is the same one you would have filled in by hand, and it validates the same way.

Let Claude write it ​

produuz.it has a Claude connector, and writing a parsing setup is what it is most useful for. Claude can read this documentation, so it knows every key on this page and what each one is for.

Add the connector — see Claude connector (MCP) — and then:

  1. Give it your properties. Export the property list of a few elements from your BIM application — one stud, one rail, one plate, one panel — and paste it in. That list is what nearly every rule is written from.

  2. Describe your panels in your own words: what marks a top rail, what marks a plate, which elements are not produced, where the phase and the batch come from.

  3. Ask for the file. For example:

    Write me an IFC parsing setup JSON for produuz.it. Here are the properties of four elements from our Tekla export. Top rails have REFERENCE starting with TR, studs W, plates P. The phase is in the PHASE property of the assembly. We do not produce steel cages.

  4. Upload it with the UPLOAD button and check every tab before saving.

Claude can also read a setup you already have. Download it, paste it in, and ask why a part is landing in the wrong category or which rules are never used.

Or let it create the setup directly ​

If you are a company administrator, Claude can skip the file and put the setup straight into Projects Settings → IFC Parsing Setups. It asks for a separate permission the first time, and you can say no and keep working with files.

What it creates is inert: no project uses it, nothing is re-analysed, and it cannot touch a setup that already exists or make one the default. You still open it, walk the tabs and assign it yourself. The checks on this page are not skipped either — they are applied by the tool, so a key that is not in the tables above is refused rather than stored.

See: Creating a parsing setup

Always check what comes back

Claude cannot see your IFC file, only what you tell it about it. It writes the rules; you check them against a real file. Nothing is saved until you press Save in the editor, and the first real test is Step 9 of the setup tutorial: split a sample file and look for parts landing in unknown.