Projects & source
Discover and read projects.
Enumerate your organization's projects, read one project's metadata, and pull its source in whichever representation you need.
List & get
GET /projects needs only a valid key (no extra scope) — even an ai_explain-only key can discover which projects exist. Results are filtered to the key's project scope and paginated with an opaque cursor.
curl -s "https://app.plcs.ai/api/v1/projects?limit=50" \
-H "Authorization: Bearer $PLCS_API_KEY"page = client.list_projects(limit=50)
for p in page.projects:
print(p.project_id, p.name, p.vendor)
detail = client.get_project(page.projects[0].project_id)
print(detail.analysis_status) # queued | running | complete | error | Nonevar page = await client.ListProjectsAsync(limit: 50);
foreach (var p in page.Projects)
Console.WriteLine($"{p.ProjectId} {p.Name} {p.Vendor}");
var detail = await client.GetProjectAsync(page.Projects[0].ProjectId);
Console.WriteLine(detail.AnalysisStatus);Read source
GET /projects/{id}/source requires code_read and supports four representations via ?format=:
| Format | Returns |
|---|---|
parsed (default) | The vendor-neutral parsed structure as JSON (programs, routines, tags, dataTypes…). Projects over the 4.5 MB inline ceiling return 413 — use raw. |
raw | The original uploaded file (L5X XML or Siemens ZIP) as a binary download. |
scl | The aggregated Structured-Text view ({ scl }). |
ladder | The aggregated ladder view ({ ladder }). |
src = client.get_source("prj_…", format="scl") # parsed | scl | ladder
print(src.scl)
raw_bytes = client.download_source("prj_…") # original L5X / ZIP bytesvar src = await client.GetSourceAsync("prj_…", "scl");
Console.WriteLine(src.Scl);
byte[] rawBytes = await client.DownloadSourceAsync("prj_…");Live HMI values
With hmi_view, GET /projects/{id}/hmi/values returns the latest tag snapshot pushed by a Desktop Companion App (DCA) session, and /hmi/history?tag=… returns recent history for one tag. These return data only while a DCA is actively streaming; with no live session you get a normal 200 with live: false and an empty tags map (not an error).
Reads need no Idempotency-Key. Listing is scoped to the key's projects; a request for a project outside the scope returns 403 project_scope_forbidden.