Inserting Families with Revit API

You can insert families programmatically at points, on faces or lines, or create hosted families.
Inserting Families is the core of creating Revit Elements – and a must-know for Revit plugin developers. 
In this post: code, examples, and everything you need to know about Inserting Families.
📌 TLDR – Summary Upfront:
To insert Families programmatically:
➡️
Get the FamilySymbol representing the family type to insert.
➡️
Use doc.Create.NewFamilyInstance to insert families at a point, on face or line, or with a host.
➡️
Remember Transactions – required for modifying Revit projects.
To prompt the user for family placement, use uiDoc.PromptForFamilyInstancePlacement (less flexible, but simpler).

Getting Family Symbol

Before inserting families, get the FamilySymbol representing a specific family type.
You can do it by specifying the family name and family type name.
C#
// Retrieve all family symbols in the document
var allFamilySymbolsInDocument = new FilteredElementCollector(doc)
	.OfClass(typeof(FamilySymbol))
	.WhereElementIsElementType()
	.Cast<FamilySymbol>().ToList();

var familyName = "Test Family";
var familyTypeName = "Test Family Type";
var familySymbol = allFamilySymbolsInDocument.FirstOrDefault(x => x.FamilyName == familyName && x.Name == familyTypeName);
🛈
If the family isn’t loaded into the document, load it using doc.LoadFamily(familyPath) before retrieving the FamilySymbol.

Inserting Family Instances

doc.Create.NewFamilyInstance enables inserting families of various types and placements.
We’ll cover three scenarios: inserting families at points (most common), creating hosted families, and placing families on faces (with advanced user-friendly selection).

Inserting a Family at a Point

The most common scenario. You need a FamilySymbol, insertion point, and StructuralType (NonStructural, Beam, Brace, Column, Footing, or UnknownFraming).
C#
var insertionPoint = new XYZ(0, 0, 0);

using var transaction = new Transaction(doc, "Create family instance");
transaction.Start();
var familyInstance_inPoint = doc.Create.NewFamilyInstance(insertionPoint, familySymbol, StructuralType.NonStructural);
transaction.Commit();
🛈
Inserting Families requires Transactions.
Although omitted in this example, using try-catch blocks bullet-proofs real plugins.

Creating a Hosted Family

For hosted families (e.g., doors hosted in a wall), you need a FamilySymbol, insertion point, StructuralType, and the hosting element.
In the previous example, the insertion point was “hard-written” in code. Here, the insertion point and hosting element are selected by the user.
C#
// Select the hosting element and insertion point 
var selectionManager = uiDoc.Selection;		
var hostingElementReference = selectionManager.PickObject(ObjectType.Element, "Select hosting element");
var hostingElement = doc.GetElement(hostingElementReference);
var pickedInsertionPoint = selectionManager.PickPoint("Pick insertion point");

using var transaction2 = new Transaction(doc, "Create hosted family instance");
transaction2.Start();
var familyInstance_hosted = doc.Create.NewFamilyInstance(pickedInsertionPoint, familySymbol, hostingElement, StructuralType.NonStructural);
transaction2.Commit();

Inserting a Face-based Family

To insert a face-based Family, you need a Family Symbol, Face reference, point on the Face, and reference direction (rotation of the created family instance).
Typically, users are prompted twice: first to select a Face, then a point. But you can improve user-experience by prompting only once. The user selects a point on a face, and the code extracts the Face reference and the point. To restrict the selection to faces, create a custom FaceSelectionFilter.
C#
// Define the family symbol for a face-based family 
var faceBasedFamilyName = "Test Face-Based Family";
var faceBasedFamilyTypeName = "Test Family Type";
var faceBasedFamilySymbol = allFamilySymbolsInDocument.FirstOrDefault(x => x.FamilyName == faceBasedFamilyName && x.Name == faceBasedFamilyTypeName);

// Select a point on a face
var pickedSurfaceReference = selectionManager.PickObject(ObjectType.PointOnElement, new FaceSelectionFilter(), "Pick point on face");
var pickedPointOnFace = pickedSurfaceReference.GlobalPoint;
var pickedFace = doc.GetElement(pickedSurfaceReference).GetGeometryObjectFromReference(pickedSurfaceReference) as Face;
var referenceDirection = pickedFace.ComputeDerivatives(new UV(0.5, 0.5)).BasisX; // determines the rotation of the created family instance
		
using var transaction3 = new Transaction(doc, "Create face-based family instance");
transaction3.Start();
var familyInstance_onFace = doc.Create.NewFamilyInstance(pickedSurfaceReference, pickedPointOnFace, referenceDirection, faceBasedFamilySymbol);
transaction3.Commit();
C#
class FaceSelectionFilter : ISelectionFilter
{
	public bool AllowElement(Element elem)
	{
		return true;
	}

	public bool AllowReference(Reference reference, XYZ position)
	{
		return reference.ElementReferenceType == ElementReferenceType.REFERENCE_TYPE_SURFACE;
	}
}

Prompting for Family Placement

To prompt the user to place families, use uiDoc.PromptForFamilyInstancePlacement.
Place the method inside a try-catch block to handle ESC and prevent errors when users finish placing.
C#
try
{	
	uiDoc.PromptForFamilyInstancePlacement(familySymbol); //Prompt: "Click to place a free instance"
}
catch { } // the user probably clicked ESC to finish placing