Docs / cufem engine API

cufem engine API

The public HTTPS API and Python client SDK for running cufemlab analyses — submit a job, read a structured verdict, and pull a signed evidence report, all against one canonical base URL.

Base URL. Every request resolves to https://app.cufemlab.secrotec.nl. The client SDK targets it by default, so you never hard‑code a host. The self‑serve web app lives at /app/ and issues the same API keys the SDK uses.

What this page covers

cufemlab exposes two equivalent front doors onto the same solver fleet:

This is the product API. Internal solver symbols are not part of the contract and are not documented here.

Authentication & keys

Create and rotate keys in the app at /app/api_keys.html, then hand the key to the client. Keep it in an environment variable — never in source control.

Auth errors. A missing or invalid key raises AuthenticationError before any work is queued. Every run consumes credits; when your balance cannot cover a job the API returns HTTP 402. Billing is fail‑closed — a job never runs "on credit". Top up or check your balance at /app/credits.html.

Quickstart

The SDK is a small, flat client: construct Client, create a project, optionally upload geometry, call analyze(…), wait, and read the result.

Submit & read a resultPython
import os
from cufemlab_client import Client

client = Client(api_key=os.environ["CUFEMLAB_API_KEY"])   # base url defaults to https://app.cufemlab.secrotec.nl

project = client.create_project("PMSM cogging pilot")

# Validated moving-band cogging workflow (GPU-first).
# max_minutes omitted -> the per-analysis default limit is used.
job = client.analyze(
    project_id=project.id,
    analysis_type="cogging_torque_movingband",
    input_params={"poles": 8, "slots": 12, "current_a": 0.0},
    gpu=True,
)

job.wait(poll_interval=10)          # blocks until the job leaves the queue
result = job.result()

print(result.verdict)                # "PASS" | "PARTIAL" | "FAIL"
print(result.value)                  # headline number for this analysis
print(result.summary)                # summary object: title, description, units
print(result.metrics)                # dict: tolerance, measured error, cross-check ...

The client surface

These are the only calls you need. Anything with a leading underscore is internal and unsupported.

max_minutes. Omit it to accept the per‑analysis default time budget — the safe choice for almost every run. Passing a value above that analysis' ceiling (or a nonsensical value) raises ValidationError; do not hard‑code a number larger than the per‑type limit.

Analysis catalog

The catalog is fifteen live workflows. Pass the exact analysis_type ID string. Two of them anchor the catalog:

validated flagship

cogging_torque_movingband

The 2‑D moving‑band / Arkkio cogging workflow — the one result that ships an independent cross‑check against open‑source FEMM and GetDP on every run.

GPU‑first · per‑run validation card cites tolerance & measured error
3-D lane · live

cufem3d_field_validation

3‑D magnetostatic edge‑element (Nédélec) solve — geometry, mesh, and the magnetic field & flux exported as VTU — returning a relative‑error field verdict.

CPU · free‑trial eligible · 1 credit · ≤ 5 min

All 15 analysis_type IDs

New thermal / core-loss / neural types (2026-07-11). The last six IDs return the same result.v1 envelope with validation_card = not_validated (the five physics types internally validated with no external passport yet; field_to_field_neural_operator an experimental surrogate). Inputs are parametric with defaults — for example core_loss_estimate takes grade and field_to_field_neural_operator takes conductivity_seed. See Thermal, core-loss & FNO for full parameters, outputs, artifacts, and runnable examples.
GPU vs CPU. The cogging and pmsm_operating_torque analyses and the new thermal lane (thermal_conduction_steady, thermal_conduction_transient, eddy_thermal_coupled, coreloss_thermal_coupled, field_to_field_neural_operator) run GPU‑first on an RTX‑class node. cufem3d_gpu_field_analysis is GPU-only and fail-closed: it does not silently fall back to CPU, and its runtime metadata reports the actual execution backend. On CPU: iron_loss_estimate, material_comparison, signed_report_generation, demo_motor_quick_check, core_loss_estimate, and cufem3d_field_validation run on CPU. The gpu flag is honored where the analysis supports it.

Uploading geometry (3-D field validation)

Geometry‑driven analyses take one or more uploaded CAD/mesh files. Upload first, then pass the file ids into analyze(…).

Upload geometry & run 3-D field validationPython
project = client.create_project("rotor 3-D field check")

# Accepted geometry: .step / .stp / .iges / .stl
geometry = client.upload_file(project.id, "rotor.step")

job = client.analyze(
    project_id=project.id,
    analysis_type="cufem3d_field_validation",
    input_params={"field_tolerance": 0.05},
    input_file_ids=[geometry.id],
)

job.wait(poll_interval=10)
result = job.result()

print(result.verdict)                        # relative-error field verdict
print(result.metrics["relative_error"])   # measured field error vs tolerance

The result envelope

job.result() returns a stable result.v1 object. Read these four fields:

Artifacts (VTU fields, waveforms, validation cards, signed PDFs) are attached to the job and also visible under /app/reports.html.

Every result carries schema_version: "result.v1", a validation_card (for the new thermal / core-loss types this is not_validated — internally validated, no external passport yet; the neural surrogate is not_validated and experimental), and a list of downloadable artifacts, each fetchable at GET /api/v1/jobs/{job_id}/artifacts/{artifact_id}.

Validation & error responses. Invalid domain parameters return HTTP 422; a job with insufficient balance returns 402 INSUFFICIENT_CREDITS; a second concurrent job over the per‑user cap returns 429 CONCURRENCY_LIMIT_EXCEEDED (max 2 concurrent). All calls require authentication (Bearer access token or X‑API‑Key).

Signed evidence reports

signed_report_generation turns a completed job into a deterministic, HMAC‑signed PDF with SHA‑256 provenance — the same bytes every time for the same inputs. Run your analysis, then generate the report and download it.

Generate a signed evidence reportPython
# 1) run any analysis to completion
run = client.analyze(
    project_id=project.id,
    analysis_type="pmsm_operating_torque",
    input_params={"poles": 8, "slots": 12, "current_a": 18.0},
    gpu=True,
)
run.wait(poll_interval=10)

# 2) produce a deterministic HMAC-signed PDF with SHA-256 provenance
report = client.analyze(
    project_id=project.id,
    analysis_type="signed_report_generation",
    input_params={"source_job_id": run.id},
)
report.wait(poll_interval=5)
report.download_report("report.pdf")   # signed PDF + provenance

Errors & limits

The SDK surfaces failures as typed exceptions and HTTP status codes so your scripts can branch on them:

What the API does — and does not — claim

Available today

  • Validated 2‑D moving‑band cogging with a per‑run FEMM/GetDP card
  • 3‑D magnetostatic field & flux validation (VTU + relative‑error verdict)
  • 2‑D operating‑torque and iron‑loss engineering estimates
  • Material comparison and deterministic HMAC‑signed reports
  • Projects, geometry upload, API keys, credits, artifacts

Maturing

  • Legacy cogging_sweep_2d path (superseded by moving‑band)
  • Broader electrical‑steel and magnet material coverage
  • GPU acceleration for the 3‑D field validation lane

Roadmap / not claimed

  • Full 3‑D motor torque with skew and end‑effects
  • Full 3‑D operating maps and a full thermal solver
  • Time‑harmonic / transient eddy‑current & conductive multiphysics
  • Any commercial‑tool (ANSYS / JMAG / COMSOL) benchmark claim

The 3‑D field validation lane is live now and is a real Nédélec magnetostatic solve of the magnetic field and flux; full 3‑D motor simulation with torque, skew, and end‑effects is on the roadmap.

Next steps