Version v1.0.0-alpha (latest)
Scenes
Create, load, and enumerate scenes. A scene is the top-level unit of work: it holds a printer/material/print-setting combination and the models placed within that printer's build volume.
Open a .form file#
POST/v1/scene/open/
Load a saved PreForm project (.form) file. A .form file can hold more than one print job, each saved as its own scene. This endpoint creates a new scene for each one in the file and reports each: its id, its name in the file, its print settings, and the ids of the models loaded into it. Fetch a scene's full state with /v1/scene/get/ or /v1/scene/model/list/.
Models keep the poses saved in the file, snapped against the printer the file was saved for. file must be a .form file, matched on the extension regardless of case; anything else is rejected before the file is read. The project name saved in the file is returned as project_name (empty when the file has none).
Loading can take a while for large or multi-scene files, so prefer ?async=true and poll the returned operation.
Error codes#
| HTTP | error.code | Cause |
|---|---|---|
| 400 | JSON_PARSE_ERROR | The request body is not a valid JSON object. |
| 400 | JSON_SCHEMA_MATCH_ERROR | The body doesn't match the request schema: file is missing, isn't a string, or an unrecognized field is present. |
| 400 | INPUT_ERROR | file's extension is not .form. |
| 400 | INVALID_QUERY_PARAMETER | async is present but not true or false. |
| 400 | OPERATION_FAILED | The file could not be loaded: it does not exist, is not a valid .form file, or its material settings could not be loaded. The message carries the underlying reason. |
| 409 | BUILD_VOLUME_LIMIT_EXCEEDED | The file holds more build volumes than the server can keep at once. No scene was created. |
Query parameters
asyncbooleanWhen
true, returns202 Acceptedimmediately with the operation's id and itsoperation_urlto poll for the result, instead of blocking until the operation completes.
Request bodyOpenFormRequest
filestringRequiredPath to the .form file to load.
Returns 200 OKobject
project_namestringRequiredThe project name saved in the file; empty when the file carries none. Set it when saving with
/v1/scene/save/.scenesarray of OpenedScenesRequiredShow child attributes
scene_idstring (uuid)RequiredUnique identifier of the new scene.
The machine/material/print-setting/layer-thickness combination used to create the scene.
Show child attributes
Canonical machine type id, e.g. "FORM-4-0".
Versioned material code, e.g. "FLGPBK05".
Print setting profile code, e.g. "DEFAULT".
Layer thickness in millimeters, always returned as a string: either a numeric string (e.g. "0.025") or the literal "ADAPTIVE" for adaptive layer thickness. Contrast with
/v1/print-setting/list/and/v1/print-setting/validate/, whoselayer_thickness_mmis a JSON number (or "ADAPTIVE").custom_print_setting_idstring (uuid)Id of the custom print setting the scene was created or updated from, if any (via
fps_file). Absent when the scene uses a material-based print setting.
new_model_idsarray of string (uuid)sRequiredIds of the newly created models, in no particular order.
scene_namestringRequiredName of this scene within the .form file, distinguishing multiple print jobs saved in one file. The scene remembers it, and
/v1/scene/save/writes it back.
The file was loaded. Reports one entry per scene saved in the file, in the order they appear in the file.
Returns 202 AcceptedOperationAccepted
operation_idstring (uuid)RequiredRandomly generated id of the tracked operation.
operation_urlstringRequiredServer-relative URL of this operation's record:
/v1/operation/get/?operation_id=<operation_id>.GETit to follow progress and retrieve the result.messagestringRequiredHuman-readable pointer to where the result will appear. Purely informational. Use
operation_urlprogrammatically.
The file was accepted for asynchronous loading (?async=true). Poll the operations endpoints with the returned id.
Response headers (202)
LocationstringServer-relative URL of the accepted operation's record, identical to the response body's
operation_url.GETit to follow progress and retrieve the result.
/v1/scene/open/from formlabs_sdk import FormlabsClient
with FormlabsClient() as client:
preform = client.preform.connect()
result = preform.open_form_file(
file="C:\\Users\\user\\Desktop\\project.form",
)curl -X POST "http://localhost:44388/v1/scene/open/" \
-H "Content-Type: application/json" \
-d '{
"file": "C:\\Users\\user\\Desktop\\project.form"
}'{
"project_name": "Print Job",
"scenes": [
{
"scene_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"scene_name": "Print Job 1",
"scene_settings": {
"machine_type": "FORM-4-0",
"material_code": "FLGPBK05",
"print_setting": "DEFAULT",
"layer_thickness_mm": "0.05"
},
"new_model_ids": [
"c2a37eb2-8e4b-4b8e-9f37-1f5f2c1a9d10"
]
}
]
}{
"project_name": "Weekly batch",
"scenes": [
{
"scene_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"scene_name": "Print Job 1",
"scene_settings": {
"machine_type": "FORM-4-0",
"material_code": "FLGPBK05",
"print_setting": "DEFAULT",
"layer_thickness_mm": "0.05"
},
"new_model_ids": [
"c2a37eb2-8e4b-4b8e-9f37-1f5f2c1a9d10",
"0d6f1e4a-2b3c-4d5e-8f90-1a2b3c4d5e6f"
]
},
{
"scene_id": "9b1dd8a0-4f6e-45c2-9a3e-77a01f2b6c55",
"scene_name": "Print Job 2",
"scene_settings": {
"machine_type": "FORM-4-0",
"material_code": "FLGPBK05",
"print_setting": "DEFAULT",
"layer_thickness_mm": "0.05"
},
"new_model_ids": []
}
]
}{
"operation_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"operation_url": "/v1/operation/get/?operation_id=7c9e6679-7425-40de-944b-e07fc1f90ae7",
"message": "Operation accepted. Poll GET /v1/operation/get/?operation_id=7c9e6679-7425-40de-944b-e07fc1f90ae7 until 'status' is SUCCEEDED or FAILED; the endpoint's response will appear in the 'result' field there."
}Create a scene#
POST/v1/scene/create/
Create a new, empty scene for a given machine/material/print-setting/ layer-thickness combination, or from a saved .fps print settings file. See /v1/print-setting/list/ for the catalog of supported combinations.
The response reports the new scene's id and the print settings it resolved to (for example, the default print_setting when the request omitted one). It does not describe the rest of the scene. To read the scene's full state, including its build volume dimensions, material usage, and layer count, call /v1/scene/get/ with the returned scene_id. That endpoint is a POST that takes the id in a JSON body:
POST /v1/scene/get/
{ "scene_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6" }Unlike /v1/scene/open/, this always completes synchronously (an empty scene has nothing to load).
Error codes#
| HTTP | error.code | Cause |
|---|---|---|
| 400 | JSON_PARSE_ERROR | The request body is not a valid JSON object. |
| 400 | JSON_SCHEMA_MATCH_ERROR | The body matches neither request shape: a required field is missing, a field has the wrong type, an unrecognized field is present, or layer_thickness_mm is a string other than "ADAPTIVE" or a numeric string. The message includes a JSON pointer to the offending field where applicable. |
| 400 | INPUT_ERROR | machine_type is (or canonicalizes to) the reserved unknown id, the combination of machine_type/material_code/print_setting/layer_thickness_mm does not match any shipped print setting, or fps_file could not be loaded or contains no usable material setting. |
Request bodyCreateSceneManual or CreateSceneFpsFile
CreateSceneManualoption 1 of 2A machine/material/print-setting/layer-thickness combination to create a scene for.
Show fields
Canonical machine type id, e.g. "FORM-4-0".
Versioned material code, e.g. "FLGPBK05".
print_settingstringPrint setting profile code, e.g. "DEFAULT".
layer_thickness_mmnumber or stringRequiredA layer thickness in millimeters, accepted as a JSON number, the literal string "ADAPTIVE" for adaptive layer thickness, or a numeric value formatted as a string (e.g. "0.025"). "ADAPTIVE" is accepted only where the settings catalog offers an adaptive variant, on older printer models (see
/v1/print-setting/list/).
CreateSceneFpsFileoption 2 of 2Create a scene from a saved .fps print settings file. Custom print settings are persisted so the scene's
scene_settings.custom_print_setting_idcan identify them later.Show fields
fps_filestringRequiredFull path to the .fps file.
ReturnsCreatedScene
scene_idstring (uuid)RequiredUnique identifier of the new scene.
The machine/material/print-setting/layer-thickness combination used to create the scene.
Show child attributes
Canonical machine type id, e.g. "FORM-4-0".
Versioned material code, e.g. "FLGPBK05".
Print setting profile code, e.g. "DEFAULT".
Layer thickness in millimeters, always returned as a string: either a numeric string (e.g. "0.025") or the literal "ADAPTIVE" for adaptive layer thickness. Contrast with
/v1/print-setting/list/and/v1/print-setting/validate/, whoselayer_thickness_mmis a JSON number (or "ADAPTIVE").custom_print_setting_idstring (uuid)Id of the custom print setting the scene was created or updated from, if any (via
fps_file). Absent when the scene uses a material-based print setting.
The scene was created.
/v1/scene/create/from formlabs_sdk import FormlabsClient
with FormlabsClient() as client:
preform = client.preform.connect()
result = preform.create_scene(
machine_type="FORM-4-0",
material_code="FLGPBK05",
print_setting="DEFAULT",
layer_thickness_mm=0.025,
)curl -X POST "http://localhost:44388/v1/scene/create/" \
-H "Content-Type: application/json" \
-d '{
"machine_type": "FORM-4-0",
"material_code": "FLGPBK05",
"print_setting": "DEFAULT",
"layer_thickness_mm": 0.025
}'from formlabs_sdk import FormlabsClient
with FormlabsClient() as client:
preform = client.preform.connect()
result = preform.create_scene(
machine_type="FS30-1-0",
material_code="FLP11B01",
layer_thickness_mm="0.11",
)curl -X POST "http://localhost:44388/v1/scene/create/" \
-H "Content-Type: application/json" \
-d '{
"machine_type": "FS30-1-0",
"material_code": "FLP11B01",
"layer_thickness_mm": "0.11"
}'from formlabs_sdk import FormlabsClient
with FormlabsClient() as client:
preform = client.preform.connect()
result = preform.create_scene(
machine_type="FUSX-1-0",
material_code="FLP12G01",
print_setting="DEFAULT",
layer_thickness_mm=0.11,
)curl -X POST "http://localhost:44388/v1/scene/create/" \
-H "Content-Type: application/json" \
-d '{
"machine_type": "FUSX-1-0",
"material_code": "FLP12G01",
"print_setting": "DEFAULT",
"layer_thickness_mm": 0.11
}'from formlabs_sdk import FormlabsClient
with FormlabsClient() as client:
preform = client.preform.connect()
result = preform.create_scene(
fps_file="C:\\Users\\user\\Desktop\\custom.fps",
)curl -X POST "http://localhost:44388/v1/scene/create/" \
-H "Content-Type: application/json" \
-d '{
"fps_file": "C:\\Users\\user\\Desktop\\custom.fps"
}'{
"scene_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"scene_settings": {
"machine_type": "FORM-4-0",
"material_code": "FLGPBK05",
"print_setting": "DEFAULT",
"layer_thickness_mm": "0.025"
}
}{
"scene_id": "9b1dd8a0-4f6e-45c2-9a3e-77a01f2b6c55",
"scene_settings": {
"machine_type": "FORM-4-0",
"material_code": "FLGPBK05",
"print_setting": "DEFAULT",
"layer_thickness_mm": "0.05",
"custom_print_setting_id": "e0f1a2b3-c4d5-4e6f-8a90-b1c2d3e4f5a6"
}
}List scenes#
GET/v1/scene/list/
List every scene currently held by the server, in project order. Project order is the order the scenes appear in the project, which is the order a user of the desktop application sees in the build list. Creating a scene appends it, so for a client that only ever creates scenes this is also creation order. A freshly started server always has at least one (default) scene, and it is first.
Error codes#
This endpoint takes no input and always succeeds. Only the shared default error can occur.
Returnsobject
scenesarray of ScenesRequiredShow child attributes
idstring (uuid)RequiredUnique identifier of the scene.
modelsarray of ModelPropertiesRequiredThe models currently in the scene.
Show child attributes
idstring (uuid)RequiredUnique identifier of the model within its scene.
namestringRequiredDisplay name used within job preparation.
A position within a printer's build volume, in millimeters, in user coordinate space.
Show child attributes
xnumberRequiredX position. 0 is the center of the build volume. Positive moves right as you face the printer.
ynumberRequiredY position. 0 is the center of the build volume. Positive moves away from you as you face the printer.
znumberRequiredVertical position. 0 is the surface of the build platform.
Orientation as Euler angles in degrees. Rotations are applied in the order z, then x, then y.
Show child attributes
xnumberRequiredRotation in degrees around the x axis (applied second).
ynumberRequiredRotation in degrees around the y axis (applied last).
znumberRequiredRotation in degrees around the z axis (applied first).
scalenumberRequiredScale factor applied to the model.
The measurement units a model was defined in.
MILLIMETERS- Model coordinates are millimeters.
INCHES- Model coordinates are inches.
bounding_boxobjectRequiredAxis-aligned bounding box of the model (including generated geometry such as supports) in scene coordinates. Group containers have an empty bounding box, serialized as all zeros.
Show child attributes
min_cornerScenePositionA position within a printer's build volume, in millimeters, in user coordinate space.
Show child attributes
xnumberRequiredX position. 0 is the center of the build volume. Positive moves right as you face the printer.
ynumberRequiredY position. 0 is the center of the build volume. Positive moves away from you as you face the printer.
znumberRequiredVertical position. 0 is the surface of the build platform.
max_cornerScenePositionA position within a printer's build volume, in millimeters, in user coordinate space.
Show child attributes
xnumberRequiredX position. 0 is the center of the build volume. Positive moves right as you face the printer.
ynumberRequiredY position. 0 is the center of the build volume. Positive moves away from you as you face the printer.
znumberRequiredVertical position. 0 is the surface of the build platform.
original_filestringRequiredPath of the file the model was imported from.
visiblebooleanRequiredWhether the model is currently shown in the scene.
has_supportsbooleanRequiredWhether support structures have been generated for the model.
is_groupbooleanRequiredWhether this entry is a Part Group container rather than a regular printable model. Group containers have zero volume and an empty bounding box.
is_cagebooleanRequiredWhether the group is a cage. Cages are a subset of groups, so
is_cage: trueimpliesis_group: true.in_boundsbooleanRequiredWhether the model lies entirely within the build volume.
raw_mesh_hashstringRequiredHash of the raw mesh data, before any transform.
canonical_model_hashstringRequiredHash of the mesh data together with its position, orientation, and scale.
Orientation and position constraints on a model, respected by automatic layout and packing operations.
FREE- Layout operations may move and rotate the model freely.
LOCKED_XY_FLIP_ENABLED- Layout may move the model and spin it about the vertical (Z) axis, and may also flip it over; it may not tilt it otherwise.
LOCKED_XY_ROTATION_FREE_TRANSLATION- Layout may move the model and spin it about the vertical (Z) axis, but not tilt it.
LOCKED_ROTATION_FREE_TRANSLATION- Layout may move the model but not rotate it at all.
FULLY_LOCKED- Layout leaves the model exactly where it is.
The machine/material/print-setting/layer-thickness combination used to create the scene.
Show child attributes
Canonical machine type id, e.g. "FORM-4-0".
Versioned material code, e.g. "FLGPBK05".
Print setting profile code, e.g. "DEFAULT".
Layer thickness in millimeters, always returned as a string: either a numeric string (e.g. "0.025") or the literal "ADAPTIVE" for adaptive layer thickness. Contrast with
/v1/print-setting/list/and/v1/print-setting/validate/, whoselayer_thickness_mmis a JSON number (or "ADAPTIVE").custom_print_setting_idstring (uuid)Id of the custom print setting the scene was created or updated from, if any (via
fps_file). Absent when the scene uses a material-based print setting.
material_usageSlaMaterialUsage or SlsMaterialUsage or UnknownMaterialUsageRequiredMaterial consumption for the scene's models. The shape depends on the scene's printer family. An unrecognized family reports an empty object.
Show child attributes
SlaMaterialUsageoption 1 of 2Material usage for an SLA-type scene (e.g. Form 4).
Show fields
volume_mlnumberRequiredTotal volume of models and supports in the scene, in milliliters.
unsupported_volume_mlnumberRequiredTotal volume of models alone, not including supports, in milliliters.
SlsMaterialUsageoption 2 of 2Material usage for an SLS-type scene (e.g. Fuse 1+, Fuse X1).
Show fields
total_powder_mlnumberRequiredTotal volume of powder used, including unsintered support powder, in milliliters.
total_powder_kgnumberRequiredTotal mass of powder used, including unsintered support powder, in kilograms.
total_sintered_powder_mlnumberRequiredVolume of powder that ends up sintered (part of the finished print), in milliliters.
total_sintered_powder_kgnumberRequiredMass of powder that ends up sintered (part of the finished print), in kilograms.
mass_packing_densitynumberRequiredRatio of sintered powder mass to the total build volume.
layer_countintegerRequiredNumber of layers the scene would slice to.
The build volume geometry for the scene's printer and material.
Show child attributes
dimensions_mmobjectRequiredBuild volume size in millimeters.
Show child attributes
xnumberRequiredynumberRequiredznumberRequired
fillet_radius_mmnumberRequiredRadius of the build volume's corner fillets, in millimeters.
The current scenes.
/v1/scene/list/from formlabs_sdk import FormlabsClient
with FormlabsClient() as client:
preform = client.preform.connect()
result = preform.list_scenes()curl "http://localhost:44388/v1/scene/list/"{
"scenes": [
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"models": [],
"scene_settings": {
"machine_type": "FORM-4-0",
"material_code": "FLGPBK05",
"print_setting": "DEFAULT",
"layer_thickness_mm": "0.025"
},
"material_usage": {
"volume_ml": 0,
"unsupported_volume_ml": 0
},
"layer_count": 0,
"build_volume": {
"dimensions_mm": {
"x": 200,
"y": 125,
"z": 210
},
"fillet_radius_mm": 3
}
},
{
"id": "9b1dd8a0-4f6e-45c2-9a3e-77a01f2b6c55",
"models": [],
"scene_settings": {
"machine_type": "PILK-1-0",
"material_code": "FLP11B01",
"print_setting": "DEFAULT",
"layer_thickness_mm": "0.11"
},
"material_usage": {
"total_powder_ml": 0,
"total_powder_kg": 0,
"total_sintered_powder_ml": 0,
"total_sintered_powder_kg": 0,
"mass_packing_density": 0
},
"layer_count": 0,
"build_volume": {
"dimensions_mm": {
"x": 165,
"y": 165,
"z": 300
},
"fillet_radius_mm": 0
}
}
]
}Get a scene#
POST/v1/scene/get/
Returns the full current state of one scene. This does not modify the scene. It is a POST (rather than GET) only because the request includes a JSON body to identify which scene to fetch.
Error codes#
| HTTP | error.code | Cause |
|---|---|---|
| 400 | JSON_PARSE_ERROR | The request body is not a valid JSON object. |
| 400 | MISSING_PARAMETER | The body has no scene_id field. |
| 400 | INPUT_ERROR | scene_id is not a well-formed UUID, or no scene with that id exists. |
Request bodyobject
scene_idstring (uuid)RequiredThe id of the scene to fetch.
ReturnsScene
idstring (uuid)RequiredUnique identifier of the scene.
modelsarray of ModelPropertiesRequiredThe models currently in the scene.
Show child attributes
idstring (uuid)RequiredUnique identifier of the model within its scene.
namestringRequiredDisplay name used within job preparation.
A position within a printer's build volume, in millimeters, in user coordinate space.
Show child attributes
xnumberRequiredX position. 0 is the center of the build volume. Positive moves right as you face the printer.
ynumberRequiredY position. 0 is the center of the build volume. Positive moves away from you as you face the printer.
znumberRequiredVertical position. 0 is the surface of the build platform.
Orientation as Euler angles in degrees. Rotations are applied in the order z, then x, then y.
Show child attributes
xnumberRequiredRotation in degrees around the x axis (applied second).
ynumberRequiredRotation in degrees around the y axis (applied last).
znumberRequiredRotation in degrees around the z axis (applied first).
scalenumberRequiredScale factor applied to the model.
The measurement units a model was defined in.
MILLIMETERS- Model coordinates are millimeters.
INCHES- Model coordinates are inches.
bounding_boxobjectRequiredAxis-aligned bounding box of the model (including generated geometry such as supports) in scene coordinates. Group containers have an empty bounding box, serialized as all zeros.
Show child attributes
min_cornerScenePositionA position within a printer's build volume, in millimeters, in user coordinate space.
Show child attributes
xnumberRequiredX position. 0 is the center of the build volume. Positive moves right as you face the printer.
ynumberRequiredY position. 0 is the center of the build volume. Positive moves away from you as you face the printer.
znumberRequiredVertical position. 0 is the surface of the build platform.
max_cornerScenePositionA position within a printer's build volume, in millimeters, in user coordinate space.
Show child attributes
xnumberRequiredX position. 0 is the center of the build volume. Positive moves right as you face the printer.
ynumberRequiredY position. 0 is the center of the build volume. Positive moves away from you as you face the printer.
znumberRequiredVertical position. 0 is the surface of the build platform.
original_filestringRequiredPath of the file the model was imported from.
visiblebooleanRequiredWhether the model is currently shown in the scene.
has_supportsbooleanRequiredWhether support structures have been generated for the model.
is_groupbooleanRequiredWhether this entry is a Part Group container rather than a regular printable model. Group containers have zero volume and an empty bounding box.
is_cagebooleanRequiredWhether the group is a cage. Cages are a subset of groups, so
is_cage: trueimpliesis_group: true.in_boundsbooleanRequiredWhether the model lies entirely within the build volume.
raw_mesh_hashstringRequiredHash of the raw mesh data, before any transform.
canonical_model_hashstringRequiredHash of the mesh data together with its position, orientation, and scale.
Orientation and position constraints on a model, respected by automatic layout and packing operations.
FREE- Layout operations may move and rotate the model freely.
LOCKED_XY_FLIP_ENABLED- Layout may move the model and spin it about the vertical (Z) axis, and may also flip it over; it may not tilt it otherwise.
LOCKED_XY_ROTATION_FREE_TRANSLATION- Layout may move the model and spin it about the vertical (Z) axis, but not tilt it.
LOCKED_ROTATION_FREE_TRANSLATION- Layout may move the model but not rotate it at all.
FULLY_LOCKED- Layout leaves the model exactly where it is.
The machine/material/print-setting/layer-thickness combination used to create the scene.
Show child attributes
Canonical machine type id, e.g. "FORM-4-0".
Versioned material code, e.g. "FLGPBK05".
Print setting profile code, e.g. "DEFAULT".
Layer thickness in millimeters, always returned as a string: either a numeric string (e.g. "0.025") or the literal "ADAPTIVE" for adaptive layer thickness. Contrast with
/v1/print-setting/list/and/v1/print-setting/validate/, whoselayer_thickness_mmis a JSON number (or "ADAPTIVE").custom_print_setting_idstring (uuid)Id of the custom print setting the scene was created or updated from, if any (via
fps_file). Absent when the scene uses a material-based print setting.
material_usageSlaMaterialUsage or SlsMaterialUsage or UnknownMaterialUsageRequiredMaterial consumption for the scene's models. The shape depends on the scene's printer family. An unrecognized family reports an empty object.
Show child attributes
SlaMaterialUsageoption 1 of 2Material usage for an SLA-type scene (e.g. Form 4).
Show fields
volume_mlnumberRequiredTotal volume of models and supports in the scene, in milliliters.
unsupported_volume_mlnumberRequiredTotal volume of models alone, not including supports, in milliliters.
SlsMaterialUsageoption 2 of 2Material usage for an SLS-type scene (e.g. Fuse 1+, Fuse X1).
Show fields
total_powder_mlnumberRequiredTotal volume of powder used, including unsintered support powder, in milliliters.
total_powder_kgnumberRequiredTotal mass of powder used, including unsintered support powder, in kilograms.
total_sintered_powder_mlnumberRequiredVolume of powder that ends up sintered (part of the finished print), in milliliters.
total_sintered_powder_kgnumberRequiredMass of powder that ends up sintered (part of the finished print), in kilograms.
mass_packing_densitynumberRequiredRatio of sintered powder mass to the total build volume.
layer_countintegerRequiredNumber of layers the scene would slice to.
The build volume geometry for the scene's printer and material.
Show child attributes
dimensions_mmobjectRequiredBuild volume size in millimeters.
Show child attributes
xnumberRequiredynumberRequiredznumberRequired
fillet_radius_mmnumberRequiredRadius of the build volume's corner fillets, in millimeters.
The scene's current state.
/v1/scene/get/from formlabs_sdk import FormlabsClient
with FormlabsClient() as client:
preform = client.preform.connect()
result = preform.get_scene(
scene_id="3fa85f64-5717-4562-b3fc-2c963f66afa6",
)curl -X POST "http://localhost:44388/v1/scene/get/" \
-H "Content-Type: application/json" \
-d '{
"scene_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
}'{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"models": [],
"scene_settings": {
"machine_type": "FORM-4-0",
"material_code": "FLGPBK05",
"print_setting": "DEFAULT",
"layer_thickness_mm": "0.025"
},
"material_usage": {
"volume_ml": 0,
"unsupported_volume_ml": 0
},
"layer_count": 0,
"build_volume": {
"dimensions_mm": {
"x": 200,
"y": 125,
"z": 210
},
"fillet_radius_mm": 3
}
}Delete a scene#
DELETE/v1/scene/delete/
Removes a scene. The server always keeps one default scene: deleting it does not remove it, but instead resets it to a fresh, empty scene of its current type. Deleting any other scene removes it entirely. A later /v1/scene/list/ no longer includes it. The delete waits for requests already running on the scene to finish.
Error codes#
| HTTP | error.code | Cause |
|---|---|---|
| 400 | JSON_PARSE_ERROR | The request body is not a valid JSON object. |
| 400 | MISSING_PARAMETER | The body has no scene_id field. |
| 400 | INPUT_ERROR | scene_id is not a well-formed UUID, or no scene with that id exists. |
Request bodyobject
scene_idstring (uuid)RequiredThe id of the scene to delete.
Returnsno body
The scene was deleted (or reset, if it was the default scene). The response has no body.
/v1/scene/delete/from formlabs_sdk import FormlabsClient
with FormlabsClient() as client:
preform = client.preform.connect()
preform.delete_scene(
scene_id="9b1dd8a0-4f6e-45c2-9a3e-77a01f2b6c55",
)curl -X DELETE "http://localhost:44388/v1/scene/delete/" \
-H "Content-Type: application/json" \
-d '{
"scene_id": "9b1dd8a0-4f6e-45c2-9a3e-77a01f2b6c55"
}'No response body.Save one or more scenes to a .form file#
POST/v1/scene/save/
Saves one or more scenes as a .form project file. Saving a single scene id writes a single-scene .form file. Saving more than one writes a multi-scene project file with one print job per scene, in the given order. project_name names the project inside the file and is what /v1/scene/open/ later returns. Each scene is written with the scene_name it had when /v1/scene/open/ created it, so a file opened and saved keeps its names; scenes made with /v1/scene/create/ have none. Scene names are limited to 128 characters and longer ones are shortened when saved. When a project name or a scene name is present, a single scene is also written as a project file so the name is kept.
Saving can take a while for scenes with many models, so prefer ?async=true and poll the returned operation.
Error codes#
| HTTP | error.code | Cause |
|---|---|---|
| 400 | JSON_PARSE_ERROR | The request body is not a valid JSON object. |
| 400 | JSON_SCHEMA_MATCH_ERROR | The body doesn't match the request schema: file is missing or empty, scene_ids is missing, not an array, or empty, or an unrecognized field is present. The message includes a JSON pointer to the offending field where applicable. |
| 400 | INPUT_ERROR | An entry in scene_ids is not a well-formed UUID, or does not refer to an existing scene. Entries are checked in order. The first bad entry is reported and no others are checked. |
| 400 | INVALID_QUERY_PARAMETER | async is present but not true or false. |
Query parameters
asyncbooleanWhen
true, returns202 Acceptedimmediately with the operation's id and itsoperation_urlto poll for the result, instead of blocking until the operation completes.
Request bodySaveSceneRequest
filestringRequiredPath to write the .form file to.
scene_idsarray of string (uuid)sRequiredIds of the scenes to save, in order. A single id saves a single-build-volume .form file. More than one saves a multi-build-volume project file.
project_namestringName of the project inside the file, returned by
/v1/scene/open/. Omitted means no name is stored.
Returns 200 OKno body
The file was saved. The response has no body.
Returns 202 AcceptedOperationAccepted
operation_idstring (uuid)RequiredRandomly generated id of the tracked operation.
operation_urlstringRequiredServer-relative URL of this operation's record:
/v1/operation/get/?operation_id=<operation_id>.GETit to follow progress and retrieve the result.messagestringRequiredHuman-readable pointer to where the result will appear. Purely informational. Use
operation_urlprogrammatically.
The file was accepted for asynchronous saving (?async=true). Poll the operations endpoints with the returned id.
Response headers (202)
LocationstringServer-relative URL of the accepted operation's record, identical to the response body's
operation_url.GETit to follow progress and retrieve the result.
/v1/scene/save/from formlabs_sdk import FormlabsClient
with FormlabsClient() as client:
preform = client.preform.connect()
preform.save_form_file(
file="C:\\Users\\user\\Desktop\\project.form",
scene_ids=["3fa85f64-5717-4562-b3fc-2c963f66afa6"],
)curl -X POST "http://localhost:44388/v1/scene/save/" \
-H "Content-Type: application/json" \
-d '{
"file": "C:\\Users\\user\\Desktop\\project.form",
"scene_ids": [
"3fa85f64-5717-4562-b3fc-2c963f66afa6"
]
}'from formlabs_sdk import FormlabsClient
with FormlabsClient() as client:
preform = client.preform.connect()
preform.save_form_file(
file="C:\\Users\\user\\Desktop\\project.form",
project_name="Tuesday batch",
scene_ids=["3fa85f64-5717-4562-b3fc-2c963f66afa6", "9b1dd8a0-4f6e-45c2-9a3e-77a01f2b6c55"],
)curl -X POST "http://localhost:44388/v1/scene/save/" \
-H "Content-Type: application/json" \
-d '{
"file": "C:\\Users\\user\\Desktop\\project.form",
"project_name": "Tuesday batch",
"scene_ids": [
"3fa85f64-5717-4562-b3fc-2c963f66afa6",
"9b1dd8a0-4f6e-45c2-9a3e-77a01f2b6c55"
]
}'No response body.{
"operation_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"operation_url": "/v1/operation/get/?operation_id=7c9e6679-7425-40de-944b-e07fc1f90ae7",
"message": "Operation accepted. Poll GET /v1/operation/get/?operation_id=7c9e6679-7425-40de-944b-e07fc1f90ae7 until 'status' is SUCCEEDED or FAILED; the endpoint's response will appear in the 'result' field there."
}Render a scene to an image file#
POST/v1/scene/render/
Renders the scene's 3D view to a .png file or a .webp flyaround animation. This does not modify the scene.
view_type selects the camera framing. ZOOM_ON_MODELS fits the visible models, FULL_BUILD_VOLUME shows the whole build volume, FULL_PLATFORM_WIDTH shows the full platform width at whatever height that implies. model_ids restricts which models are visible in the render and are candidates for ZOOM_ON_MODELS framing. Omitting this field means every model in the scene is included.
A flyaround is a multi-frame .webp animation orbiting the scene at a fixed pitch: either an explicit list of yaw/pitch keyframes, or an evenly-spaced frame_count of frames around a full turn starting from yaw/pitch. Flyarounds cannot be saved as .png.
Rendering can take a while for large scenes, so prefer ?async=true and poll the returned operation.
Error codes#
| HTTP | error.code | Cause |
|---|---|---|
| 400 | JSON_PARSE_ERROR | The request body is not a valid JSON object. |
| 400 | JSON_SCHEMA_MATCH_ERROR | The body fails the request schema: scene_id or file missing, a field has the wrong type or an out-of-range value (including a view_type outside the documented values and a frame_count below 1), flyaround_transform has neither transform nor frame_count, or an unrecognized field is present. |
| 400 | INPUT_ERROR | scene_id is not a well-formed UUID, no scene with that id exists, or file ends in .png while flyaround_transform is present. |
| 400 | INVALID_QUERY_PARAMETER | async is present but not true or false. |
| 400 | OPERATION_FAILED | view_type is ZOOM_ON_MODELS and no selected models are visible, or the render could not be written to file. |
| 404 | NOT_FOUND | A model in model_ids does not exist in the scene. |
Query parameters
asyncbooleanWhen
true, returns202 Acceptedimmediately with the operation's id and itsoperation_urlto poll for the result, instead of blocking until the operation completes.
Request bodyRenderRequest
scene_idstring (uuid)RequiredThe id of the scene to render.
filestringRequiredPath to save the rendered image to. Must end in
.pngor.webp..webpis required whenflyaround_transformis present.model_idsarray of string (uuid)sIds of the models to make visible in the render (and candidates for
ZOOM_ON_MODELSframing). Omitted or[]means every model in the scene.view_typeenum RenderViewTypeCamera framing for a render.
ZOOM_ON_MODELS- Frame the camera to fit the selected, visible models.
FULL_BUILD_VOLUME- Frame the camera to fit the whole build volume.
FULL_PLATFORM_WIDTH- Frame the camera to the platform's full width, at whatever height that implies.
image_size_pxintegerMaximum image width/height, in pixels. The render is square.
crop_to_modelsbooleanWhether to crop the frame tightly around the visible models instead of leaving margin.
yawnumberCamera yaw, in degrees. Ignored when
flyaround_transform.transformis present.pitchnumberCamera pitch, in degrees. Ignored when
flyaround_transform.transformis present.flyaround_transformanyRenders a
.webpanimation instead of a single.png. Provide either an explicittransformkeyframe list, orframe_countto auto-generate evenly-spaced frames around a full turn starting from the top-levelyaw/pitch. At least one of the two is required.Show child attributes
transformarray of FlyaroundKeyframesExplicit list of camera keyframes to render, one per animation frame.
Show child attributes
yawnumberRequiredCamera yaw for this frame, in degrees.
pitchnumberRequiredCamera pitch for this frame, in degrees.
frame_countintegerNumber of evenly-spaced frames to render around a full 360-degree turn. Ignored if
transformis present.ensure_constant_sizebooleanWhen true, every frame is rendered at the same size (the largest needed by any frame) instead of each frame being cropped independently.
Returns 200 OKno body
The image was saved. The response has no body.
Returns 202 AcceptedOperationAccepted
operation_idstring (uuid)RequiredRandomly generated id of the tracked operation.
operation_urlstringRequiredServer-relative URL of this operation's record:
/v1/operation/get/?operation_id=<operation_id>.GETit to follow progress and retrieve the result.messagestringRequiredHuman-readable pointer to where the result will appear. Purely informational. Use
operation_urlprogrammatically.
The render was accepted for asynchronous processing (?async=true). Poll the operations endpoints with the returned id.
Response headers (202)
LocationstringServer-relative URL of the accepted operation's record, identical to the response body's
operation_url.GETit to follow progress and retrieve the result.
/v1/scene/render/from formlabs_sdk import FormlabsClient
from formlabs_preform_api.models import RenderViewType
with FormlabsClient() as client:
preform = client.preform.connect()
preform.render_scene(
scene_id="3fa85f64-5717-4562-b3fc-2c963f66afa6",
file="C:\\Users\\user\\Desktop\\preview.png",
model_ids=["c2a37eb2-8e4b-4b8e-9f37-1f5f2c1a9d10", "389bef9a-fb24-6a18-4cd1-5c634e76db34"],
view_type=RenderViewType("ZOOM_ON_MODELS"),
image_size_px=1024,
)curl -X POST "http://localhost:44388/v1/scene/render/" \
-H "Content-Type: application/json" \
-d '{
"scene_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"file": "C:\\Users\\user\\Desktop\\preview.png",
"model_ids": [
"c2a37eb2-8e4b-4b8e-9f37-1f5f2c1a9d10",
"389bef9a-fb24-6a18-4cd1-5c634e76db34"
],
"view_type": "ZOOM_ON_MODELS",
"image_size_px": 1024
}'from formlabs_sdk import FormlabsClient
from formlabs_preform_api.models import RenderViewType
with FormlabsClient() as client:
preform = client.preform.connect()
preform.render_scene(
scene_id="3fa85f64-5717-4562-b3fc-2c963f66afa6",
file="C:\\Users\\user\\Desktop\\flyaround.webp",
view_type=RenderViewType("FULL_BUILD_VOLUME"),
flyaround_transform={
"frame_count": 8,
},
)curl -X POST "http://localhost:44388/v1/scene/render/" \
-H "Content-Type: application/json" \
-d '{
"scene_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"file": "C:\\Users\\user\\Desktop\\flyaround.webp",
"view_type": "FULL_BUILD_VOLUME",
"flyaround_transform": {
"frame_count": 8
}
}'from formlabs_sdk import FormlabsClient
from formlabs_preform_api.models import RenderViewType
with FormlabsClient() as client:
preform = client.preform.connect()
preform.render_scene(
scene_id="3fa85f64-5717-4562-b3fc-2c963f66afa6",
file="C:\\Users\\user\\Desktop\\flyaround.webp",
view_type=RenderViewType("FULL_BUILD_VOLUME"),
flyaround_transform={
"transform": [{
"yaw": 0,
"pitch": 45,
}, {
"yaw": 45,
"pitch": 45,
}, {
"yaw": 90,
"pitch": 45,
}, {
"yaw": 135,
"pitch": 45,
}, {
"yaw": 180,
"pitch": 45,
}, {
"yaw": 225,
"pitch": 45,
}, {
"yaw": 270,
"pitch": 45,
}, {
"yaw": 315,
"pitch": 45,
}],
},
)curl -X POST "http://localhost:44388/v1/scene/render/" \
-H "Content-Type: application/json" \
-d '{
"scene_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"file": "C:\\Users\\user\\Desktop\\flyaround.webp",
"view_type": "FULL_BUILD_VOLUME",
"flyaround_transform": {
"transform": [
{
"yaw": 0,
"pitch": 45
},
{
"yaw": 45,
"pitch": 45
},
{
"yaw": 90,
"pitch": 45
},
{
"yaw": 135,
"pitch": 45
},
{
"yaw": 180,
"pitch": 45
},
{
"yaw": 225,
"pitch": 45
},
{
"yaw": 270,
"pitch": 45
},
{
"yaw": 315,
"pitch": 45
}
]
}
}'No response body.{
"operation_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"operation_url": "/v1/operation/get/?operation_id=7c9e6679-7425-40de-944b-e07fc1f90ae7",
"message": "Operation accepted. Poll GET /v1/operation/get/?operation_id=7c9e6679-7425-40de-944b-e07fc1f90ae7 until 'status' is SUCCEEDED or FAILED; the endpoint's response will appear in the 'result' field there."
}Estimate a scene's print time#
POST/v1/scene/estimate-print-time/
Returns a fast, approximate total print time for a scene. For a more accurate calculation and breakdown, use /v1/scene/calculate-print-time/. This does not modify the scene.
Fast estimation is only available for SLA-type scenes (e.g. Form 4). SLS-type scenes (e.g. Fuse 1+, Fuse X1) do not support it and return 422.
Error codes#
| HTTP | error.code | Cause |
|---|---|---|
| 400 | JSON_PARSE_ERROR | The request body is not a valid JSON object. |
| 400 | MISSING_PARAMETER | The body has no scene_id field. |
| 400 | INPUT_ERROR | scene_id is not a well-formed UUID, or no scene with that id exists. |
| 400 | OPERATION_FAILED | The estimation task could not run (e.g. the scene was deleted while the request was in flight). |
| 422 | ESTIMATION_NOT_SUPPORTED | The scene's machine type does not support fast print time estimation. |
Request bodyobject
scene_idstring (uuid)RequiredThe id of the scene to estimate.
Returnsobject
total_print_time_sintegerRequiredEstimated total print time, in seconds.
The estimated total print time.
/v1/scene/estimate-print-time/from formlabs_sdk import FormlabsClient
with FormlabsClient() as client:
preform = client.preform.connect()
result = preform.estimate_print_time(
scene_id="3fa85f64-5717-4562-b3fc-2c963f66afa6",
)curl -X POST "http://localhost:44388/v1/scene/estimate-print-time/" \
-H "Content-Type: application/json" \
-d '{
"scene_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
}'{
"total_print_time_s": 1800
}Calculate a scene's full print time breakdown#
POST/v1/scene/calculate-print-time/
Runs the full print time calculation for a scene and returns a breakdown of total, pre-print, and printing time. This does not modify the scene.
This calculation is available for every supported machine type, but can take noticeably longer to run than /v1/scene/estimate-print-time/, so prefer ?async=true and poll the returned operation.
cool_to_removal_time_s and additional_cool_to_room_temp_time_s are only present for Fuse 1+ scenes.
Error codes#
| HTTP | error.code | Cause |
|---|---|---|
| 400 | JSON_PARSE_ERROR | The request body is not a valid JSON object. |
| 400 | MISSING_PARAMETER | The body has no scene_id field. |
| 400 | INPUT_ERROR | scene_id is not a well-formed UUID, or no scene with that id exists. |
| 400 | INVALID_QUERY_PARAMETER | async is present but not true or false. |
| 400 | OPERATION_FAILED | The print time calculation could not complete for this scene. |
Query parameters
asyncbooleanWhen
true, returns202 Acceptedimmediately with the operation's id and itsoperation_urlto poll for the result, instead of blocking until the operation completes.
Request bodyobject
scene_idstring (uuid)RequiredThe id of the scene to calculate print time for.
Returns 200 OKobject
total_print_time_sintegerRequiredTotal print time in seconds, including pre-print time and, for Fuse 1+ scenes, cooling time.
preprint_time_sintegerRequiredTime spent on pre-print steps (e.g. heating the tank), in seconds.
printing_time_sintegerRequiredTime spent actively printing, in seconds.
cool_to_removal_time_sintegerFuse 1+ scenes only. Time to cool the print to a safe removal temperature, in seconds.
additional_cool_to_room_temp_time_sintegerFuse 1+ scenes only. Additional time to cool the print to room temperature after removal, in seconds.
The full print time breakdown.
Returns 202 AcceptedOperationAccepted
operation_idstring (uuid)RequiredRandomly generated id of the tracked operation.
operation_urlstringRequiredServer-relative URL of this operation's record:
/v1/operation/get/?operation_id=<operation_id>.GETit to follow progress and retrieve the result.messagestringRequiredHuman-readable pointer to where the result will appear. Purely informational. Use
operation_urlprogrammatically.
The calculation was accepted for asynchronous processing (?async=true). Poll the operations endpoints with the returned id.
Response headers (202)
LocationstringServer-relative URL of the accepted operation's record, identical to the response body's
operation_url.GETit to follow progress and retrieve the result.
/v1/scene/calculate-print-time/from formlabs_sdk import FormlabsClient
with FormlabsClient() as client:
preform = client.preform.connect()
result = preform.calculate_print_time(
scene_id="3fa85f64-5717-4562-b3fc-2c963f66afa6",
)curl -X POST "http://localhost:44388/v1/scene/calculate-print-time/" \
-H "Content-Type: application/json" \
-d '{
"scene_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
}'{
"total_print_time_s": 420,
"preprint_time_s": 120,
"printing_time_s": 300
}{
"total_print_time_s": 480,
"preprint_time_s": 120,
"printing_time_s": 300,
"cool_to_removal_time_s": 60,
"additional_cool_to_room_temp_time_s": 600
}{
"operation_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"operation_url": "/v1/operation/get/?operation_id=7c9e6679-7425-40de-944b-e07fc1f90ae7",
"message": "Operation accepted. Poll GET /v1/operation/get/?operation_id=7c9e6679-7425-40de-944b-e07fc1f90ae7 until 'status' is SUCCEEDED or FAILED; the endpoint's response will appear in the 'result' field there."
}Update a scene's printer/material settings#
POST/v1/scene/update/
Change an existing scene's machine/material/print-setting/ layer-thickness combination, or apply a saved .fps print settings file. Accepts the same combinations as /v1/scene/create/, plus the scene_id to update.
Models already in the scene are kept and repositioned to fit the new machine/material's build volume. Returns the settings that were applied. Fetch /v1/scene/get/ for the scene's resulting state.
Error codes#
| HTTP | error.code | Cause |
|---|---|---|
| 400 | JSON_PARSE_ERROR | The request body is not a valid JSON object. |
| 400 | JSON_SCHEMA_MATCH_ERROR | The body matches neither request shape: a required field (including scene_id) is missing, a field has the wrong type, an unrecognized field is present, or layer_thickness_mm is a string other than "ADAPTIVE" or a numeric string. The message includes a JSON pointer to the offending field where applicable. |
| 400 | INPUT_ERROR | scene_id is not a well-formed UUID, no scene with that id exists, machine_type is the reserved unknown id, the combination of machine_type/material_code/print_setting/layer_thickness_mm does not match any shipped print setting, or fps_file could not be loaded. |
Request bodyUpdateSceneManual or UpdateSceneFpsFile
UpdateSceneManualoption 1 of 2A new machine/material/print-setting/layer-thickness combination to apply to the scene.
Show fields
scene_idstring (uuid)RequiredThe id of the scene to update.
Canonical machine type id, e.g. "FORM-4-0".
Versioned material code, e.g. "FLGPBK05".
print_settingstringPrint setting profile code, e.g. "DEFAULT".
layer_thickness_mmnumber or stringRequiredA layer thickness in millimeters, accepted as a JSON number, the literal string "ADAPTIVE" for adaptive layer thickness, or a numeric value formatted as a string (e.g. "0.025"). "ADAPTIVE" is accepted only where the settings catalog offers an adaptive variant, on older printer models (see
/v1/print-setting/list/).
UpdateSceneFpsFileoption 2 of 2Update a scene from a saved .fps print settings file. Custom print settings are persisted so the scene's
scene_settings.custom_print_setting_idcan identify them later.Show fields
scene_idstring (uuid)RequiredThe id of the scene to update.
fps_filestringRequiredFull path to the .fps file.
Returnsobject
The machine/material/print-setting/layer-thickness combination used to create the scene.
Show child attributes
Canonical machine type id, e.g. "FORM-4-0".
Versioned material code, e.g. "FLGPBK05".
Print setting profile code, e.g. "DEFAULT".
Layer thickness in millimeters, always returned as a string: either a numeric string (e.g. "0.025") or the literal "ADAPTIVE" for adaptive layer thickness. Contrast with
/v1/print-setting/list/and/v1/print-setting/validate/, whoselayer_thickness_mmis a JSON number (or "ADAPTIVE").custom_print_setting_idstring (uuid)Id of the custom print setting the scene was created or updated from, if any (via
fps_file). Absent when the scene uses a material-based print setting.
The scene was updated. Returns the settings that were applied, including the print setting and layer thickness they resolved to.
/v1/scene/update/from formlabs_sdk import FormlabsClient
with FormlabsClient() as client:
preform = client.preform.connect()
result = preform.update_scene(
scene_id="3fa85f64-5717-4562-b3fc-2c963f66afa6",
machine_type="FORM-4-0",
material_code="FLGPBK05",
print_setting="DEFAULT",
layer_thickness_mm=0.025,
)curl -X POST "http://localhost:44388/v1/scene/update/" \
-H "Content-Type: application/json" \
-d '{
"scene_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"machine_type": "FORM-4-0",
"material_code": "FLGPBK05",
"print_setting": "DEFAULT",
"layer_thickness_mm": 0.025
}'from formlabs_sdk import FormlabsClient
with FormlabsClient() as client:
preform = client.preform.connect()
result = preform.update_scene(
scene_id="3fa85f64-5717-4562-b3fc-2c963f66afa6",
fps_file="C:\\Users\\user\\Desktop\\custom.fps",
)curl -X POST "http://localhost:44388/v1/scene/update/" \
-H "Content-Type: application/json" \
-d '{
"scene_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"fps_file": "C:\\Users\\user\\Desktop\\custom.fps"
}'{
"scene_settings": {
"machine_type": "FORM-4-0",
"material_code": "FLGPBK05",
"print_setting": "DEFAULT",
"layer_thickness_mm": "0.025"
}
}Upload a scene's sliced job to a printer#
POST/v1/scene/print/
Runs the full slicing pipeline for a scene and uploads the resulting job to printer, identified by serial name, IP address, or Fleet Control Queue id. This does not modify the scene.
print_now controls whether the job prints immediately or is queued: omitting it defers to the printer's current ready_to_print_now state. Requesting print_now: true on a printer that cannot start immediately (e.g. a Cloud Queue) fails with OPERATION_FAILED.
This can take a while, especially finding the printer on the network, so prefer ?async=true and poll the returned operation.
Error codes#
| HTTP | error.code | Cause |
|---|---|---|
| 400 | INVALID_QUERY_PARAMETER | async is present but not true or false. |
| 400 | JSON_PARSE_ERROR | The request body is not a valid JSON object. |
| 400 | JSON_SCHEMA_MATCH_ERROR | scene_id, printer, or job_name is missing or not a string, find_printer_timeout_seconds is present but not a non-negative integer, print_now is present but not a boolean, or an unrecognized field is present. |
| 400 | INPUT_ERROR | scene_id is not a well-formed UUID, or no scene with that id exists. |
| 400 | OPERATION_FAILED | The printer could not be found within find_printer_timeout_seconds, slicing failed, or the job could not be uploaded (e.g. print_now: true on a printer that cannot print immediately). The message carries the underlying reason. |
Query parameters
asyncbooleanWhen
true, returns202 Acceptedimmediately with the operation's id and itsoperation_urlto poll for the result, instead of blocking until the operation completes.
Request bodyPrintSceneRequest
scene_idstring (uuid)RequiredThe id of the scene to print.
printerstringRequiredPrinter serial name, IP address, or Fleet Control Queue id.
job_namestringRequiredName of the job.
find_printer_timeout_secondsintegerNumber of seconds to wait to find the given printer.
print_nowbooleanIf true, the job must print immediately. This fails with
OPERATION_FAILEDif the printer'sready_to_print_nowstatus is not true. If false, the job is uploaded to the printer's local queue instead of printing immediately. Omitting this field defers to the printer's currentready_to_print_nowstate: prints immediately if ready, queues otherwise.
Returns 200 OKobject
job_idstring (uuid)RequiredThe id of the newly created print job.
The job was uploaded to the printer.
Returns 202 AcceptedOperationAccepted
operation_idstring (uuid)RequiredRandomly generated id of the tracked operation.
operation_urlstringRequiredServer-relative URL of this operation's record:
/v1/operation/get/?operation_id=<operation_id>.GETit to follow progress and retrieve the result.messagestringRequiredHuman-readable pointer to where the result will appear. Purely informational. Use
operation_urlprogrammatically.
The request was accepted for asynchronous processing (?async=true). Poll the operations endpoints with the returned id.
Response headers (202)
LocationstringServer-relative URL of the accepted operation's record, identical to the response body's
operation_url.GETit to follow progress and retrieve the result.
/v1/scene/print/from formlabs_sdk import FormlabsClient
with FormlabsClient() as client:
preform = client.preform.connect()
result = preform.print_scene(
scene_id="3fa85f64-5717-4562-b3fc-2c963f66afa6",
printer="ArtfulChameleon",
job_name="My Job",
)curl -X POST "http://localhost:44388/v1/scene/print/" \
-H "Content-Type: application/json" \
-d '{
"scene_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"printer": "ArtfulChameleon",
"job_name": "My Job"
}'from formlabs_sdk import FormlabsClient
with FormlabsClient() as client:
preform = client.preform.connect()
result = preform.print_scene(
scene_id="3fa85f64-5717-4562-b3fc-2c963f66afa6",
printer="192.168.1.42",
job_name="My Job",
print_now=True,
)curl -X POST "http://localhost:44388/v1/scene/print/" \
-H "Content-Type: application/json" \
-d '{
"scene_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"printer": "192.168.1.42",
"job_name": "My Job",
"print_now": true
}'{
"job_id": "9c858901-8a57-4791-81fe-4c455b099bc9"
}{
"operation_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"operation_url": "/v1/operation/get/?operation_id=7c9e6679-7425-40de-944b-e07fc1f90ae7",
"message": "Operation accepted. Poll GET /v1/operation/get/?operation_id=7c9e6679-7425-40de-944b-e07fc1f90ae7 until 'status' is SUCCEEDED or FAILED; the endpoint's response will appear in the 'result' field there."
}Get a scene's print-job metadata#
POST/v1/scene/metadata/
Returns the job-metadata JSON document PreForm embeds in print jobs for this scene: the subset that can be computed from the scene's current state without slicing. The document is a passthrough of the printer job-metadata format: keys are PascalCase, the exact shape depends on the scene's printer family, and fields beyond the example will appear. This does not modify the scene. It is a POST (rather than GET) only because the request includes a JSON body to identify the scene.
Error codes#
| HTTP | error.code | Cause |
|---|---|---|
| 400 | JSON_PARSE_ERROR | The request body is not a valid JSON object. |
| 400 | MISSING_PARAMETER | The body has no scene_id field. |
| 400 | INPUT_ERROR | scene_id is not a well-formed UUID, or no scene with that id exists. |
| 400 | OPERATION_FAILED | The metadata could not be computed (e.g. the scene was deleted while the request was in flight). |
Request bodyobject
scene_idstring (uuid)RequiredThe id of the scene.
Returnsobject
The scene's print-job metadata.
/v1/scene/metadata/from formlabs_sdk import FormlabsClient
with FormlabsClient() as client:
preform = client.preform.connect()
result = preform.get_scene_metadata(
scene_id="3fa85f64-5717-4562-b3fc-2c963f66afa6",
)curl -X POST "http://localhost:44388/v1/scene/metadata/" \
-H "Content-Type: application/json" \
-d '{
"scene_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
}'{
"MaterialCode": "FLGPGR05",
"AllowedMachineTypeIds": [
"FORM-4-0"
]
}