# LearnRevitAPI > Learn the Revit API and pyRevit, one button at a time. LearnRevitAPI is where Erik Frits teaches the Revit API and pyRevit: how architects, engineers and BIM people automate Revit with Python and build their own tools. Below is the catalogue, generated from the site itself: every training with its courses, modules and lessons, a title and one line each, then everything else the site publishes. Lessons are read inside the platform: a free training needs an account, a paid one the training. The Revit API reference itself is not here: it lives at https://rvtdocs.com/mcp. ## Trainings ### Free pyRevit Course: Fast-Track https://learnrevitapi.com/fast-track/ Free pyRevit Fast-Track: 13 short lessons to set up pyRevit, build your first custom extension and start automating Revit today. (free with an account) #### pyRevit https://learnrevitapi.com/fast-track/01-pyrevit/ ##### Setup pyRevit https://learnrevitapi.com/fast-track/01-pyrevit/01-setup-pyrevit/ ##### Create Your Own Extension https://learnrevitapi.com/fast-track/01-pyrevit/02-create-your-own-extension/ ##### Anatomy of pyRevit https://learnrevitapi.com/fast-track/01-pyrevit/03-anatomy-of-pyrevit/ #### Code-Editor https://learnrevitapi.com/fast-track/02-code-editor/ ##### Choosing Your Code Editor https://learnrevitapi.com/fast-track/02-code-editor/04-choosing-your-code-editor/ ##### Quick-Start VS Code https://learnrevitapi.com/fast-track/02-code-editor/05-quick-start-vs-code/ ##### Quick-Start Cursor IDE https://learnrevitapi.com/fast-track/02-code-editor/06-quick-start-cursor-ide/ ##### IDE Tour for Beginners https://learnrevitapi.com/fast-track/02-code-editor/07-ide-tour-for-beginners/ #### First Button https://learnrevitapi.com/fast-track/03-first-button/ ##### Framework for new pyRevit Tools https://learnrevitapi.com/fast-track/03-first-button/08-framework-for-new-pyrevit-tools/ ##### Create Your First Button https://learnrevitapi.com/fast-track/03-first-button/09-create-your-first-button/ ##### Refine and add more features https://learnrevitapi.com/fast-track/03-first-button/10-refine-and-add-more-features/ ##### Stress-Test your tools https://learnrevitapi.com/fast-track/03-first-button/11-stress-test-your-tools/ ##### Super-Charge with AI https://learnrevitapi.com/fast-track/03-first-button/12-super-charge-with-ai/ ##### What's Next? https://learnrevitapi.com/fast-track/03-first-button/13-whats-next/ ### 21-Day pyRevit Challenge https://learnrevitapi.com/join-challenge/ (paid, for members of this training) #### Week 1 https://learnrevitapi.com/pyrevit-challenge/week-1/ #### Week 2 https://learnrevitapi.com/pyrevit-challenge/week-2/ #### Week 3 https://learnrevitapi.com/pyrevit-challenge/week-3/ #### Week 4 https://learnrevitapi.com/pyrevit-challenge/week-4/ #### Bonuses https://learnrevitapi.com/pyrevit-challenge/bonuses/ ### Academy https://learnrevitapi.com/join-ai-lab/ (paid, for members of this training) #### LRA-Basics https://learnrevitapi.com/academy/basics/ #### LRA-Advanced https://learnrevitapi.com/academy/advanced/ #### LRA-Modern UI https://learnrevitapi.com/academy/modern-ui/ ### LRA AI-Lab https://learnrevitapi.com/join-ai-lab/ (paid, for members of this training) #### 01. Quick-Start Setup https://learnrevitapi.com/ai-lab/01-quick-start/ #### 02. Feel the Vibes https://learnrevitapi.com/ai-lab/02-feel-the-vibes/ #### 03. Build pyRevit AI Engine https://learnrevitapi.com/ai-lab/03-pyrevit-ai-engine/ #### LLM Wiki https://learnrevitapi.com/ai-lab/llm-wiki/ #### Git for BIM Developers https://learnrevitapi.com/ai-lab/git-for-bim-developers/ #### Live Call Recordings https://learnrevitapi.com/ai-lab/live-calls/ ## Blog ### NEW pyRevit 7.0 (Fast-Engine, MCP, WebView2 + NEW UI Workflow) https://learnrevitapi.com/blog/pyrevit-7/ What is new in pyRevit 7.0: the faster engine, the built-in MCP server for AI agents, WebView2 windows and the new UI workflow. ### pyRevit MCP: Connect ANY AI Agent to Revit (Full Setup Guide) https://learnrevitapi.com/blog/pyrevit-mcp-setup/ Full pyRevit MCP setup guide: connect Claude, Codex or any AI agent to Revit so it can read your model and run pyRevit tools from a simple prompt. ### The Full pyRevit Course for Beginners (Setup → Your First Button) https://learnrevitapi.com/blog/fast-track-pyrevit-course/ Free pyRevit course for beginners: install pyRevit, set up your code editor and extension, and build your first custom Revit button from scratch. ### Convert Revit Coordinates with Revit API [Internal, Project, Survey] https://learnrevitapi.com/blog/convert-coordinate-systems-in-revit-api-draft/ ## Coordinate Systems in Revit ![](https://learnrevitapi.com/media/img/f4/f44b74acac557856f81aa8c6be8465be785400da2fac196ae08a43c3e8e73f5d.png) Revit Coordinate Systems is a tricky topic! Especially if you want to automate coordinates with Revit API… In Revit API you need to be careful with units that you use. Because It's so easy to use the wrong units and then spend hours looking for an issue…. *(Yeah… I've been there multiple times)* **But don't worry,** **I already did the hard work for you!** It took me couple of days, but now I have my own Coordinate Converter than anyone can use in in 3 lines of code. Yeah… It's that simple. And the best part? I'm going to share it with you in a moment for FREE. It will literally save you days of headache All you'll have to do: - Copy my code - Understand 3 lines on how to use it - And enjoy the simplicity of working with coordinates But before I share my grand solution… Let's have a quick overview of coordinate systems in Revit. ## Coordinate Systems Overview There are **3 Coordinate Systems **in Revit: - **Internal **(Used as the internal system of Revit, used in Revit API) - **Project (Based on Project Base Point)** - **Survey **(Based on Survey Point) Also keep in mind that in Revit we can set True North rotation, which will not affect all systems similar. - **Internal **- True North Rotation is not applied - **Project **- True North Rotation is not applied - **Survey **- All coordinates will be affected by True North Rotation.   ![](https://learnrevitapi.com/media/img/c2/c23ca160bb63adada142d3eee1abb1157f2202aadb484d47fd3ffc53f7635f88.png) ## ## 💡Pro Tip Before you begin… I really recommend creating proper tags to easily read correct values., ![](https://learnrevitapi.com/media/img/83/83a6c118eb68fdde7bda1985231354e0255f037c8956189327dffa79f8f980a9.png) It can easily help you avoid using the wrong units or data as you create your custom tools. You can also push it a step further and create tags for both: - Metric Units - Internal Units This way you'll instantly notice if you're exporting the wrong data. (Trust me, it happens way too often with coordinates when we use API…) Alright and now - let's look into API ## Revit Coordinates in Revit API First of all you need to know that Revit API always uses Internal Coordinate System in feet. That means that when you read XYZ values, you'll get them in **Internal System in Feet**. And it also means that you need to prepare your XYZ values in **Internal System in Feet**. And if you forget this, don't be surprised when your elements are flying in the sky above your project. Now let's look at how to convert coordinates with Code. ## My Coordinate Converter Class I've prepared a custom class that can convert XYZ points from any coorindate system into any other with just a few lines. 🚨**ANd Spoiler alert:** you're about to see code that might scare many of you. But y**ou don't even have to understand anything about it.** 👉 You just copy the code below. 👉 Paste in your script 👉 Scroll to next example to undrstand how to use it ```python # ╦╔╦╗╔═╗╔═╗╦═╗╔╦╗╔═╗ # ║║║║╠═╝║ ║╠╦╝ ║ ╚═╗ # ╩╩ ╩╩ ╚═╝╩╚═ ╩ ╚═╝ #================================================== from Autodesk.Revit.DB import * # ╦ ╦╔═╗╦═╗╦╔═╗╔╗ ╦ ╔═╗╔═╗ # ╚╗╔╝╠═╣╠╦╝║╠═╣╠╩╗║ ║╣ ╚═╗ # ╚╝ ╩ ╩╩╚═╩╩ ╩╚═╝╩═╝╚═╝╚═╝ #================================================== uidoc = __revit__.ActiveUIDocument doc = __revit__.ActiveUIDocument.Document #type:Document # ╔═╗╦ ╔═╗╔═╗╔═╗ # ║ ║ ╠═╣╚═╗╚═╗ # ╚═╝╩═╝╩ ╩╚═╝╚═╝ #================================================== class CoordSys: Internal = 'Internal' Project = 'Project' Survey = 'Survey' class PointConverter: pt_internal = None pt_survey = None pt_project = None def __init__(self, input_pt, coord_sys=CoordSys.Internal): """Converte 2.0 for converting XYZ points between any Coordinate Systems. Args: :param input_pt: The XYZ point in Internal Coordinate System. Adjust coord_sys argument if you want to use other Cooridnate Systems. :param coord_sys: The coordinate system chosen from CoordSys helper class (Internal, Project, Survey) Example: pt = elem.Location.Point converter = PointConverter(pt, CoordSys.Internal) pt_survey = pt_converter.pt_survey # XYZ in FEET pt_survey_m = pt_converter.pt_survey_m # XYZ in Meters pt_converter.print_in_metric(coord_sys=CoordSys.Survey) """ # type: float, float, float, CoordSys # Get Systems Transform srvTrans = self._GetSurveyTransform() projTrans = self._GetProjectTransform() #1️⃣ INPUT - INTERNAL COORDINATE SYSTEM if coord_sys == CoordSys.Internal: self.pt_internal = input_pt self.pt_survey = self._ApplyInverseTransformation(srvTrans, self.pt_internal) self.pt_project = self._ApplyInverseTransformation(projTrans, self.pt_internal) #2️⃣ INPUT - PROJECT COORDINATE SYSTEM elif coord_sys == CoordSys.Project: self.pt_project = input_pt self.pt_internal = self._ApplyTransformation(projTrans, self.pt_project) self.pt_survey = self._ApplyInverseTransformation(srvTrans, self.pt_internal) #3️⃣ - SURVEY COORDINATE SYSTEM elif coord_sys == CoordSys.Survey: self.pt_survey = input_pt self.pt_internal = self._ApplyTransformation(srvTrans, self.pt_survey) self.pt_project = self._ApplyInverseTransformation(projTrans, self.pt_internal) else: raise Exception("Wrong argument value for 'coord_sys' in PointConverter class.") #🧮 Create Metric Points self.pt_internal_m = self._get_metric_XYZ(CoordSys.Internal) self.pt_project_m = self._get_metric_XYZ(CoordSys.Project) self.pt_survey_m = self._get_metric_XYZ(CoordSys.Survey) def print_in_metric(self, coord_sys, units=UnitTypeId.Meters): """ Helper function to display coordinates in Metric System.""" pt_m = self._get_metric_XYZ(coord_sys, units) print('[{}] XYZ: ({}m, {}m, {}m)'.format(coord_sys, pt_m.X, pt_m.Y, pt_m.Z)) #🚧 INTERNAL HELPING METHODS def _get_metric_XYZ(self, coord_sys, units=UnitTypeId.Meters): """Convert the point into Metric XYZ System. NB! Do not use it with Revit API as it needs internal units.""" # Get Point With Correct Coordinate System if coord_sys == CoordSys.Internal: pt = self.pt_internal elif coord_sys == CoordSys.Project: pt = self.pt_project elif coord_sys == CoordSys.Survey: pt = self.pt_survey # Convert Values to Metric X_m = UnitUtils.ConvertFromInternalUnits(pt.X, units) Y_m = UnitUtils.ConvertFromInternalUnits(pt.Y, units) Z_m = UnitUtils.ConvertFromInternalUnits(pt.Z, units) return (XYZ(X_m, Y_m, Z_m)) def _GetSurveyTransform(self): """Gets the Active Project Locations Transform (Survey).""" return doc.ActiveProjectLocation.GetTotalTransform() def _GetProjectTransform(self): """Get the Project Base Points Transform.""" basePtLoc = next((l for l in FilteredElementCollector(doc) \ .OfClass(ProjectLocation) \ .WhereElementIsNotElementType() \ .ToElements() if l.Name == "Project"), None) return basePtLoc.GetTotalTransform() def _ApplyInverseTransformation(self, t, pt): """Applies the inverse transformation of the given Transform to the given point.""" return t.Inverse.OfPoint(pt) def _ApplyTransformation(self, t, pt): """Applies the transformation of the given Transform to the given point.""" return t.OfPoint(pt) ``` ### 🤔How to use it? **And now, here's the gravy for your fries.** As I mentioned: You don't even need to understand the class I provided. You just need to use a few methods. 💡And please **pay attention to units that you use !** And here's an example: Where I'll take a list of generic models ('EF_Box') And I'm going to convert internal coordinates into Project and Survey Systems. ```python # Get Elements elems = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_GenericModel).WhereElementIsNotElementType().ToElements() boxes = [e for e in elems if 'EF_Box' in e.Name] # ⚠️ I use specific Type Name to filter... # Get Coordinates for box in boxes: # Get Location pt = box.Location.Point # Internal Coordinate System (defualt) # 👉 Convert XYZ Point pt_converter = PointConverter(pt, CoordSys.Internal) pt_survey = pt_converter.pt_survey # XYZ - SURVEY WITH VALUES IN FEET pt_survey_m = pt_converter.pt_survey_m # XYZ - SURVEY WITH VALUES IN METERS pt_project = pt_converter.pt_project # XYZ - PROJECT WITH VALUES IN FEET pt_project_m = pt_converter.pt_project_m # XYZ - PROJECT WITH VALUES IN METERS # Extra Function To Print Correct Data Display Results pt_converter.print_in_metric(coord_sys=CoordSys.Survey) ``` Simple right? As you can see I've used XYZ with internal coordinates to create Survey and Project coordinates. But I could also import some excel data of Survey coordinates, and convert it back into internal… You get the point. **Enjoy working with Revit API Coordinates like a Pro.** **Feel free to mention this article to others coders!** **They'll love you for that.** Happy Coding. ### The Ultimate Python Course For Beginners (Learn How To Code in 2026) https://learnrevitapi.com/blog/12hr-python-course/ Learn Python from zero in one free 12-hour course for beginners: the core concepts step by step, the foundation you need before you automate Revit. ### Revit API Course For Beginners (The Best Way To Get Started) https://learnrevitapi.com/blog/intro-revit-api-course/ Revit API course for beginners: what the Revit API is, how to read its documentation and how to write your first scripts. The best way to get started. ### pyRevit WPF Form for Asking user for Multiple Paths https://learnrevitapi.com/blog/pyrevit-wpf-form-for-getting-file-paths/ ## EF-WPF Form Here is the overview of the form that I will give you the code for. It's simple, but yet very elegant to collect multiple paths. But also you can extend the functionality if you know how to work with WPF. Happy Coding! [EF-WPF Form overview](https://player.mediadelivery.net/embed/750622/47822ac1-930d-4e53-8d48-e0ce8e665eb6) ## Folderstructure To create WPF forms you need to create .xaml file and then use it inside of your python script. ![](https://learnrevitapi.com/media/img/91/91e1cf68c3205294b502df6a5466bc9bd1f212e9600d4895a13d76c1f1c5e210.png) Let's break them down one by one. ## .XAML Script **Xaml **- is the file format for WPF forms, which is used for designing front-end of the forms. In this case you have to create a file `FormFolderPaths.xaml` in the same folder as your`script.py`, because I will be referencing the name of the file inside the python file. Here is the code: ```text