SafetiBase is a tool designed for Collaborative sharing of structured H&S information using BIM and it’s based on the PAS 1192-6:2018 industry standards. Meanwhile, Dynamo is a visual scripting environment for designers working in Revit or Civils 3D. It’s brilliant for creating complex geometry and automating specific tasks. In this case, we are going to bring SafetiBase & Revit model together using Dynamo & 3D Repo’s APIs. Here is what we are going to achieve:

  • Retrieve Risk information from 3D Repo using an API

  • Filter the information for relevant fields

  • Create Risk Pins in Revit as they appear in 3D Repo (using Revit Family)

  • Add Risk information to the pins (Instance Parameter)

Initial Setup

Let’s get you setup so that you can execute the Dynamo Script without a problem.
First of all, you will need access to the following:

  1. Autodesk Revit 2021

  2. Dynamo for Revit (version or later)

  3. 3D Repo account

  4. Model access in 3D Repo

  5. Download the Script & Revit Family

If you are looking to test this workflow, you will need to upload a model to 3D Repo and create some example Risks.
Alternatively, if you are looking to use it on a live project, make sure that you have access to a model containing the risk information you need.

Revit & Dynamo Configuration


  • Activate Revit and load a model

  • Go to the Insert Tab and select Load Family

  • Locate the sample SafetiBase Pin.rfa

  • Go to the Manage Tab and select Dynamo Player

Dynamo Player

  • Click on the Folder icon to open directory browser

  • Locate the folder with Dynamo Script

  • Select the folder and click OK

  • Click on the User Inputs icon to bring up the menu

User Inputs

In order to perform the API request, please fill out the following fields of information:

  • API Key for Authentication

  • Teamspace to locate a project

  • Model ID to locate a model

  • Family Name (should you choose to rename the SafetiBase Pin.rfa file)

Here is where you can find the above information required to execute the script:

  • Teamspace
    This is where your model exists. In this example, the model we are using is called Structure and it exists in the project called SafetiBase which belongs to Bogdan_D Teamspace

  • Model ID
    This is a unique model ID number which we use in our API call. You can retrieve the ID number by going to the Model Settings menu as shown below. Copy & Paste the number to user inputs in Dynamo.

  • API Key
    Use API Key to authenticate your API request. It is an easy way to gain access to your model data without using your Username & Password. Therefore, it is important to not disclose your API key to anyone who is not authorised to gain access to your project’s data. Treat it as your personal password.

Run the Script

Once you have gathered all the relevant information just copy & paste it into the user input fields. All that’s left to do is click on the Play button in Dynamo player as shown below.

Dynamo Script

Risk Data Design Script

//Check if the Project is rotated
angle = Element.GetParameterValueByName(PBP, "Angle to True North");
degrees = angle > 0;
info = DSCore.Data.ParseJSON(data);

//Get Risk Data
Risk_points = Dictionary.ValueAtKey(info, "position");
AR = Dictionary.ValueAtKey(info, "assigned_roles");
//Create Issue Points
pointX = List.GetItemAtIndex(Risk_points<1>, 0);
pointY = (List.GetItemAtIndex(Risk_points<1>, 2) * -1);
pointZ = List.GetItemAtIndex(Risk_points<1>, 1);

//Translate points to Revit Origin
vector = Vector.ByTwoPoints((CoordinateSystem.Origin(CoordinateSystem.Identity())),Coordinates.SurveyPoint());
points = Geometry.Translate(Point.ByCoordinates(pointX, pointY, pointZ), vector);

//Rotated points
Survey_Point = Coordinates.SurveyPoint();
Zvector = Vector.ZAxis();
points2 = Geometry.Rotate(points<1L>, Survey_Point<1L>, Zvector<1L>, angle<1L>);

//Filter Risk Data
MitigationStatus = Dictionary.ValueAtKey(info, "mitigation_Status") == "agreed_fully";
AllRisks = Dictionary.ValueAtKey(info, "level_of_risk");
// Risk Parameters
test = Dictionary.ValueAtKey(info, ["name","desc","level_of_risk"]);
Risk_fields = ["_id","name", "desc", "level_of_risk", "owner", "category", "associated_activity", "element", "risk_factor", "scope", "location_desc", "assigned_roles"];
fields_values = List.AddItemToEnd(urls<1>, List.Flatten(Dictionary.ValueAtKey(info<1>, Risk_fields<2>)@L3<1>, -1)<1>);
// Filer Risks by Mitigation
AllPins = List.Flatten([degrees ? points2<1L> : points<1L>]);
FilteredPoints = List.FilterByBoolMask(AllPins, MitigationStatus);
FilteredRisks = List.FilterByBoolMask(AllRisks, MitigationStatus);
FilteredFields = List.FilterByBoolMask(fields_values, MitigationStatus);
location = Dictionary.ValueAtKey(FilteredPoints, "out");
LevelofRisk = Dictionary.ValueAtKey(FilteredRisks, "out");
R_fields = Dictionary.ValueAtKey(FilteredFields, "out");

//Family Types
family = Family.ByName(name);
VeryLow = FamilyType.ByFamilyAndName(family, "Very Low");
Low = FamilyType.ByFamilyAndName(family, "Low");
Moderate = FamilyType.ByFamilyAndName(family, "Moderate");
High = FamilyType.ByFamilyAndName(family, "High");
VeryHigh = FamilyType.ByFamilyAndName(family, "Very High");

//Create Family Instances
Pin_location = List.GetItemAtIndex(location, List.AllIndicesOf(LevelofRisk, [0,1,2,3,4]));
familyinstance = FamilyInstance.ByPoint([VeryLow,Low,Moderate,High,VeryHigh], Pin_location);

//Add Parameter values to the pins
Family_Parameters = ["Risk ID", "Risk Name", "Risk Description", "Level of Risk", "Risk Owner", "Category", "Associated Activity", "Element Type", "Risk Factor", "Construction Scope", "Location", "Assigned To","Risk Screenshot (URL Link)"];
// Values from 3D Repo
Pin_parameters = List.Clean(List.GetItemAtIndex(R_fields, List.AllIndicesOf(LevelofRisk, [0,1,2,3,4])), false);
pins = List.Clean(familyinstance, false);
set = Element.SetParameterByName(pins<1L>, Family_Parameters@L3<1L>, Pin_parameters<1L>);

Did this answer your question?