SAF Import / Export Pro / Studio
FrameAI supports round-trip interop with Scia Engineer, Tekla Structural Designer, and Nemetschek via the Structural Analysis Format (SAF) v2.x — the de-facto open exchange format for steel analytical models.
Import an existing SAF workbook to bring member geometry, sections, materials, and load cases into FrameAI. Export any completed project back to SAF so your analysis team can pick up the updated model in their preferred tool without re-entry.
SAF Workbook Format
A SAF workbook is a standard .xlsx file. FrameAI reads and writes the following sheets per the SAF v2.1 specification:
| Sheet | Purpose | Import | Export |
|---|---|---|---|
| Project | Project metadata — name, author, date, revision | ✓ | ✓ |
| Material | Steel/concrete grade definitions with E, G, Poisson | ✓ | ✓ |
| CrossSection | Profile catalogue — maps to HEA/HEB/IPE/UC/UB/HSS | ✓ | ✓ |
| StructuralNode | 3D node coordinates (X, Y, Z) + support conditions | ✓ | ✓ |
| StructuralCurveMember | 1D beam/column members with start/end nodes | ✓ | ✓ |
| LoadCase | Permanent/variable/accidental load cases per EN 1990 | ✓ | ✓ |
| LoadCombination | ULS/SLS design combinations | ✓ | ✓ |
| PointLoad | Concentrated forces/moments at nodes | ✓ | ✓ |
| LineLoad | Distributed loads along curve members | ✓ | ✓ |
| SurfaceLoad | Area loads on 2D elements | ✓ | ✓ |
Import — POST /api/import/saf
Upload a SAF .xlsx file via multipart/form-data. FrameAI parses the workbook, maps sections and materials, and returns a structured JSON summary.
POST /api/import/saf
Request
curl -X POST https://frameai-structural.polsia.app/api/import/saf \
-F "email=engineer@example.com" \
-F "file=@scia-portal-frame.xlsx"
Response (200 OK)
{
"project": { "name": "Warehouse Portal Frame", "author": "J. de Vries", "date": "2026-06-07" },
"member_count": 24,
"node_count": 18,
"cross_section_count": 3,
"material_count": 1,
"load_case_count": 4,
"load_combo_count": 6,
"load_count": 0,
"warnings": [],
"members": [ ... ],
"nodes": [ ... ],
"cross_sections": [ ... ],
"materials": [ ... ],
"load_cases": [ ... ],
"load_combinations": [ ... ]
}
Error responses
| Status | Meaning |
|---|---|
| 400 | No file uploaded or file is not .xlsx |
| 401 | email not provided or user not found |
| 402 | Free-tier account — upgrade required |
| 422 | File is not a valid SAF workbook (xlsx parse error) |
Export — GET /api/projects/:id/export.saf
Download a SAF workbook containing all completed jobs in a project. Member geometry, sections, and load data from every done job are merged into a single workbook compatible with Scia/Tekla.
GET /api/projects/:id/export.saf?email=...
Request
curl "https://frameai-structural.polsia.app/api/projects/42/export.saf?email=engineer@example.com" \
-o project-42-saf.xlsx
Response
On success: Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet with Content-Disposition: attachment; filename="frameai-project-42-saf.xlsx".
| Status | Meaning |
|---|---|
| 200 | .xlsx binary stream |
| 402 | Free-tier account — upgrade required |
| 404 | Project not found or not owned by this account |
| 409 | No completed jobs in this project |
Section Mapping
FrameAI maps SAF cross-section names (as Scia/Tekla produce them) to its internal EN 10365 section library. The mapping covers the full HEA/HEB/HEM, IPE, UC/UB, and HSS/RHS/CHS families.
Spacing variants are normalised — HEB 300, HEB300, and heb300 all map to the same internal section.
If a section name is not found in the catalogue, a warning is appended to warnings[] and the raw label is passed through as a custom section. FrameAI will still import the member; Eurocode section class checks will flag an unresolved profile.
Examples
| SAF label | FrameAI section |
|---|---|
| HEB 300 | HEB300 |
| IPE 500 | IPE500 |
| UC 254x254x89 | UC254x254x89 |
| SHS 200x200x8 | SHS200x200x8 (custom) |
Material Mapping
Material names are matched case-insensitively to EN standard grades. Sub-grade suffixes (JR, J0, J2, M, ML, N, NL) are stripped and the base grade is used.
| SAF material | EN grade |
|---|---|
| S355JR / S355J0 / S355NL | S355 |
| S275J2 | S275 |
| S460ML | S460 |
| C30/37 | C30/37 |
Unknown materials default to S355 with a warning.
Worked Example — HEB 300 Portal Frame
A 20 m × 7 m portal frame with 4 columns HEB 300 S355, 2 rafters IPE 500 S355, and 18 purlins IPE 200 S235 exported from Scia Engineer and imported into FrameAI:
# 1. Export from Scia → File → Export → SAF workbook
# Save as portal-frame.xlsx
# 2. Import into FrameAI
curl -X POST https://frameai-structural.polsia.app/api/import/saf \
-F "email=engineer@firm.com" \
-F "file=@portal-frame.xlsx"
# Response: member_count=24, warnings=[]
# 3. Export FrameAI project back to SAF (after running the pipeline on a PDF)
curl "https://frameai-structural.polsia.app/api/projects/7/export.saf?email=engineer@firm.com" \
-o frameai-portal-frame.xlsx
# 4. Open frameai-portal-frame.xlsx in Tekla Structural Designer
# Import → SAF → Select file → confirm 24 members loaded
Warnings Reference
| code | Meaning |
|---|---|
| UNMATCHED_SECTION | Section label not in standard library — imported as custom |
| UNMATCHED_MATERIAL | Material not in EN catalogue — defaulted to closest match |
| UNSUPPORTED_ELEMENT | Non-linear or 2D element type — imported as beam with warning |
All warnings are non-fatal. The import always completes; it is the caller's responsibility to review warnings[] and decide whether to proceed or correct the source model.