Building Revit Add-ins for MEP Engineers: Automating What Shouldn't Be Manual

The 20-Minute Task You Do 50 Times a Week

If you're an MEP engineer using Revit, you know the drill. Tag every duct segment with its size. Manually. One by one. Across 12 floors of a hospital. Then do it again when the architect moves a wall and half your duct routing changes.

Revit is an incredible tool, but it wasn't built with MEP productivity in mind. The architectural features are mature and polished. The MEP side? It works, but it's full of repetitive, click-heavy workflows that scream "automate me."

That's where the Revit API comes in. With a custom add-in, you can turn a 20-minute manual task into a 2-second button click.

This post walks through three practical Revit add-ins I've built (or wish I'd built earlier) during my time as a BIM engineer — what they do, why they matter, and what I learned building them.

What You Need to Get Started

The Revit API is a C#/.NET interface that ships with every Revit installation. To build add-ins, you need:

  1. Visual Studio (the free Community edition works)
  2. Revit installed on your machine (the API DLLs live in the Revit installation folder)
  3. A .NET Framework class library project — this compiles into a DLL that Revit loads on startup
  4. An .addin manifest — a small XML file that tells Revit where your DLL lives and which commands it contains

You place the manifest in Revit's add-ins folder, and your custom commands appear in the ribbon the next time you launch Revit. No installer needed for internal tools.

Add-in 1: Auto-Tag All Untagged Duct Segments

The problem: Revit's built-in "Tag All" feature places tags on every element, but it doesn't skip already-tagged elements — so you get duplicates. It also places tags at default positions that often overlap, requiring manual cleanup.

What the add-in does:

  1. Scans the active view for all duct segments
  2. Identifies which ones already have tags (by cross-referencing existing tag elements)
  3. Tags only the untagged ducts, placing each tag at the midpoint of the duct segment

The key Revit API concept here is the FilteredElementCollector — it lets you query elements by category, type, and view scope. You use it to collect all duct curves in the current view, then collect all existing tags to build a set of already-tagged element IDs. The difference between the two sets gives you your untagged ducts.

Time saved: On a typical floor plan with 200+ duct segments, this turns a 15-minute manual task into a 2-second click. Across a 12-floor hospital project, that's hours saved per week.

Add-in 2: Export MEP System Data to JSON

The problem: You need to get data out of Revit and into an external tool — a calculation engine, a web dashboard, a cost estimation spreadsheet, or an HVAC sizing platform like Mepbau. Revit's built-in export options (schedules, IFC) are either too limited or too broad.

What the add-in does:

  1. Collects all pipe elements from the model
  2. Reads key parameters for each pipe: system type, material, diameter, length, start/end coordinates, and level
  3. Converts all units from Revit's internal imperial system (feet) to metric (meters and millimeters)
  4. Writes a clean, structured JSON file to your desktop

Why JSON? Once your BIM data is in JSON, you can feed it to virtually any external system — a web-based dashboard, a Python calculation engine, a cost estimation tool, or a custom reporting pipeline. JSON is the universal data interchange format for web and cloud tools.

Critical gotcha: The Revit API stores all dimensions in imperial units internally — lengths in feet, areas in square feet — regardless of your project's display units. You must convert manually: multiply feet by 0.3048 for meters, or by 304.8 for millimeters. Forget this and your exported data will be wildly wrong.

Add-in 3: Batch Parameter Writer from CSV

The problem: You've exported element data to Excel for review, made corrections or additions (insulation thickness, fire rating, manufacturer), and now you need to push those values back into Revit. Manually. One element at a time. For 800 duct segments.

What the add-in does:

  1. Opens a file dialog for you to select a CSV file
  2. Reads the CSV where the first column is the Element ID and the remaining columns are parameter names
  3. For each row, finds the element in the model and writes the parameter values
  4. Handles different data types (text, numbers, integers) automatically
  5. Reports how many parameters were updated and how many elements weren't found

The CSV format is simple: a header row with "ElementId" in the first column followed by parameter names, and data rows below. For example:

ElementIdInsulationThicknessFireRatingManufacturer
123456730F90Rockwool
123456850F120Armaflex

This is the kind of add-in that pays for its development time in a single use. I once had to update insulation parameters on 800+ duct segments — without this tool, it would have been a full day of clicking.

Five Revit API Lessons the Hard Way

After building several add-ins, these are the traps I've learned to avoid:

1. Everything Requires a Transaction

Any modification to the Revit model — even changing a single parameter value — must be wrapped in a transaction. Try to modify something outside a transaction and you'll get a runtime crash. Read-only operations (collecting elements, reading parameters) don't need one.

2. Imperial Units Are Everywhere

As mentioned above, Revit stores everything in feet internally. Always convert. I keep a mental cheat sheet: feet × 304.8 = mm, feet × 0.3048 = m, sq feet × 0.0929 = m².

3. Element IDs Are Not Stable

Element IDs can change when you sync to central, upgrade the file, or perform certain operations. If you need to reference elements persistently (across sessions or in external databases), use the UniqueId (a GUID string) instead of the numeric ElementId.

4. Filter at the Database Level

The FilteredElementCollector filters elements at Revit's internal database level — it's fast. Collecting all elements and then filtering with your own logic is slow. Always push as much filtering into the collector as possible: filter by category, by class, by view, by type.

5. Regenerate After Geometry Changes

If you modify geometry (move a duct, resize a pipe) and immediately try to read properties, you might get stale values. You need to explicitly tell Revit to regenerate its internal state after geometry modifications.

Distribution and the Future

For internal tools, the .addin manifest approach is all you need. For wider distribution, options include:

  • Autodesk App Store — The official marketplace. Requires review but gives you visibility among Revit users worldwide.
  • Installer package — An MSI or EXE that places the DLL and manifest in the right directory automatically.
  • Company deployment — For firms, push via group policy or a shared network path.

Looking ahead, Autodesk is pushing Autodesk Platform Services (APS), formerly Forge — cloud-based APIs for working with Revit models without the desktop application. This opens up possibilities for web-based tools that read and write Revit data via REST APIs, which is where I see the industry heading.

For now, though, the desktop Revit API remains the most powerful way to automate MEP workflows. If you're an MEP engineer and you haven't tried building an add-in yet — start with the auto-tagger. The time it saves will convince you to keep going.


Building Revit tools for MEP workflows? I'd love to see what you're working on. Reach out at hello@laborsam.com.