Skip to main content

Rockwell L5X Import & Export (Studio 5000 Exchange)

June 2026 | ControlForge v1.0.1069

L5X is Rockwell Studio 5000's XML program-exchange format. ControlForge can import an L5X — converting its UDTs, Add-On Instructions, and program routines into Structured Text — and export a ControlForge program back out as an L5X download for round-tripping into Studio 5000. A third endpoint validates ST against the RLL (ladder-export) subset so you know up front whether a program will export cleanly to ladder.

There are no L5X_* ST functions — this is an HTTP-only project-exchange surface (tag l5x). Get a token first:

TOKEN=$(curl -s -X POST http://localhost:8302/api/auth/login \
-H 'Content-Type: application/json' \
-d '{"username":"goplc","password":"goplc"}' | python3 -c 'import sys,json;print(json.load(sys.stdin)["token"])')

Import an L5X

POST /api/l5x/import takes the raw L5X XML in a JSON body and converts it to ST. UDTs are loaded as a combined l5x_types library, each AOI as its own library, and every program routine as a ControlForge program. The converted project is saved as a side effect.

curl -s -X POST http://localhost:8302/api/l5x/import \
-H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
-d '{"content":"<?xml version=\"1.0\"?><RSLogix5000Content>...</RSLogix5000Content>"}'

To send a file from disk, fold it into the content field:

python3 -c 'import json,sys; print(json.dumps({"content": open(sys.argv[1]).read()}))' MyProgram.L5X \
| curl -s -X POST http://localhost:8302/api/l5x/import \
-H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' --data-binary @-

The response summarizes the conversion:

FieldMeaning
successtrue when the L5X parsed and converted
summaryHuman-readable summary of what the L5X contained
udtsCount of user-defined types loaded as the l5x_types library
aoisCount of Add-On Instructions loaded as individual libraries
programsCount of program routines imported as ST programs
warningsNon-fatal conversion notes (unsupported constructs, load issues)
errorsConversion errors from the converter

A body with no content returns 400 {"error":"content is required"}; an XML that won't parse returns 400 with the parse error. Always read warnings — a converted-but-lossy import lands its caveats there rather than failing.


Export a program as L5X

POST /api/l5x/export renders one ControlForge program to a Rockwell L5X and streams it back as an application/xml attachment. program is the program name (required); controller_name is an optional controller label written into the L5X.

curl -s -X POST http://localhost:8302/api/l5x/export \
-H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
-d '{"program":"Main","controller_name":"Line3"}' \
-o Main.L5X

On success you get the XML file (Content-Disposition: attachment; filename="Main.L5X"). The failure cases come back as JSON instead: missing program400, unknown program → 404 {"error":"Program 'X' not found"}, export failure → 400 with the reason.


Validate RLL (ladder-export) compatibility

POST /api/l5x/validate-rll checks whether ST source stays inside the RLL-compatible subset — the constructs that survive a clean export to ladder logic. Run it before exporting if the destination is ladder rather than ST routines.

curl -s -X POST http://localhost:8302/api/l5x/validate-rll \
-H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
-d '{"source":"PROGRAM Main\nVAR x : BOOL; END_VAR\nx := TRUE;\nEND_PROGRAM"}'
# → {"valid":true}

The result is:

FieldMeaning
validtrue when the source is fully RLL-compatible
errorsArray of {line, message, hint} for unsupported constructs (omitted when none)
warningsArray of {line, message, hint} for constructs that export but lose fidelity

A body with no source returns 400 {"error":"source is required"}; ST that won't parse returns 400 with the parse error. A valid:true with no errors means the program will export to ladder cleanly; entries in errors point at the exact lines to rework.


Notes & limits

  • Import is destructive to the project state — it loads converted programs/libraries and saves. Take a snapshot first if you want to roll back.
  • Export is one program at a time — pass a single program name; there's no whole-project L5X export on this surface.
  • Validate before exporting to ladder. ST that's perfectly valid as a ControlForge program can still contain constructs RLL can't represent; validate-rll is the gate, and its errors[].hint tells you how to bring a line into the subset.
  • Conversion is best-effort, not bit-perfect. Studio 5000 and ControlForge are different runtimes — read warnings on import and treat the result as a starting point to review, not a guaranteed equivalent.