Formlabs Developers
Download PreForm Insider to start developing with the PreForm API.
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#

HTTPerror.codeCause
400JSON_PARSE_ERRORThe request body is not a valid JSON object.
400JSON_SCHEMA_MATCH_ERRORThe body doesn't match the request schema: file is missing, isn't a string, or an unrecognized field is present.
400INPUT_ERRORfile's extension is not .form.
400INVALID_QUERY_PARAMETERasync is present but not true or false.
400OPERATION_FAILEDThe 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.
409BUILD_VOLUME_LIMIT_EXCEEDEDThe file holds more build volumes than the server can keep at once. No scene was created.

Query parameters

  • asyncboolean

    When true, returns 202 Accepted immediately with the operation's id and its operation_url to poll for the result, instead of blocking until the operation completes.

    Defaults to false

Request bodyOpenFormRequest

  • filestringRequired

    Path to the .form file to load.

Returns 200 OKobject

  • project_namestringRequired

    The project name saved in the file; empty when the file carries none. Set it when saving with /v1/scene/save/.

  • scenesarray of OpenedScenesRequired
    Show child attributes
    • scene_idstring (uuid)Required

      Unique identifier of the new scene.

    • scene_settingsSceneTypeRequired

      The machine/material/print-setting/layer-thickness combination used to create the scene.

      Show child attributes
      • machine_typestringRequired

        Canonical machine type id, e.g. "FORM-4-0".

      • material_codestringRequired

        Versioned material code, e.g. "FLGPBK05".

      • print_settingstringRequired

        Print setting profile code, e.g. "DEFAULT".

      • layer_thickness_mmstringRequired

        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/, whose layer_thickness_mm is 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)sRequired

      Ids of the newly created models, in no particular order.

    • scene_namestringRequired

      Name 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)Required

    Randomly generated id of the tracked operation.

  • operation_urlstringRequired

    Server-relative URL of this operation's record: /v1/operation/get/?operation_id=<operation_id>. GET it to follow progress and retrieve the result.

  • messagestringRequired

    Human-readable pointer to where the result will appear. Purely informational. Use operation_url programmatically.

The file was accepted for asynchronous loading (?async=true). Poll the operations endpoints with the returned id.

Response headers (202)

  • Locationstring

    Server-relative URL of the accepted operation's record, identical to the response body's operation_url. GET it to follow progress and retrieve the result.

POST/v1/scene/open/
Python
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",
    )
Terminal
curl -X POST "http://localhost:44388/v1/scene/open/" \
  -H "Content-Type: application/json" \
  -d '{
    "file": "C:\\Users\\user\\Desktop\\project.form"
  }'
Response
JSON
{
  "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"
      ]
    }
  ]
}
JSON
{
  "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": []
    }
  ]
}
JSON
{
  "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:

JSON
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#

HTTPerror.codeCause
400JSON_PARSE_ERRORThe request body is not a valid JSON object.
400JSON_SCHEMA_MATCH_ERRORThe 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.
400INPUT_ERRORmachine_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 2

    A machine/material/print-setting/layer-thickness combination to create a scene for.

    Show fields
    • machine_typestringRequired

      Canonical machine type id, e.g. "FORM-4-0".

    • material_codestringRequired

      Versioned material code, e.g. "FLGPBK05".

    • print_settingstring

      Print setting profile code, e.g. "DEFAULT".

    • layer_thickness_mmnumber or stringRequired

      A 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 2

    Create a scene from a saved .fps print settings file. Custom print settings are persisted so the scene's scene_settings.custom_print_setting_id can identify them later.

    Show fields
    • fps_filestringRequired

      Full path to the .fps file.

ReturnsCreatedScene

  • scene_idstring (uuid)Required

    Unique identifier of the new scene.

  • scene_settingsSceneTypeRequired

    The machine/material/print-setting/layer-thickness combination used to create the scene.

    Show child attributes
    • machine_typestringRequired

      Canonical machine type id, e.g. "FORM-4-0".

    • material_codestringRequired

      Versioned material code, e.g. "FLGPBK05".

    • print_settingstringRequired

      Print setting profile code, e.g. "DEFAULT".

    • layer_thickness_mmstringRequired

      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/, whose layer_thickness_mm is 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.

POST/v1/scene/create/
Python
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,
    )
Terminal
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
  }'
Python
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",
    )
Terminal
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"
  }'
Python
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,
    )
Terminal
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
  }'
Python
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",
    )
Terminal
curl -X POST "http://localhost:44388/v1/scene/create/" \
  -H "Content-Type: application/json" \
  -d '{
    "fps_file": "C:\\Users\\user\\Desktop\\custom.fps"
  }'
Response
JSON
{
  "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"
  }
}
JSON
{
  "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 ScenesRequired
    Show child attributes
    • idstring (uuid)Required

      Unique identifier of the scene.

    • modelsarray of ModelPropertiesRequired

      The models currently in the scene.

      Show child attributes
      • idstring (uuid)Required

        Unique identifier of the model within its scene.

      • namestringRequired

        Display name used within job preparation.

      • positionScenePositionRequired

        A position within a printer's build volume, in millimeters, in user coordinate space.

        Show child attributes
        • xnumberRequired

          X position. 0 is the center of the build volume. Positive moves right as you face the printer.

        • ynumberRequired

          Y position. 0 is the center of the build volume. Positive moves away from you as you face the printer.

        • znumberRequired

          Vertical position. 0 is the surface of the build platform.

      • orientationEulerAnglesRequired

        Orientation as Euler angles in degrees. Rotations are applied in the order z, then x, then y.

        Show child attributes
        • xnumberRequired

          Rotation in degrees around the x axis (applied second).

        • ynumberRequired

          Rotation in degrees around the y axis (applied last).

        • znumberRequired

          Rotation in degrees around the z axis (applied first).

      • scalenumberRequired

        Scale factor applied to the model.

      • unitsenum UnitsRequired

        The measurement units a model was defined in.

        Currently one of the following; more may be added:

        MILLIMETERS
        Model coordinates are millimeters.
        INCHES
        Model coordinates are inches.
      • bounding_boxobjectRequired

        Axis-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_cornerScenePosition

          A position within a printer's build volume, in millimeters, in user coordinate space.

          Show child attributes
          • xnumberRequired

            X position. 0 is the center of the build volume. Positive moves right as you face the printer.

          • ynumberRequired

            Y position. 0 is the center of the build volume. Positive moves away from you as you face the printer.

          • znumberRequired

            Vertical position. 0 is the surface of the build platform.

        • max_cornerScenePosition

          A position within a printer's build volume, in millimeters, in user coordinate space.

          Show child attributes
          • xnumberRequired

            X position. 0 is the center of the build volume. Positive moves right as you face the printer.

          • ynumberRequired

            Y position. 0 is the center of the build volume. Positive moves away from you as you face the printer.

          • znumberRequired

            Vertical position. 0 is the surface of the build platform.

      • original_filestringRequired

        Path of the file the model was imported from.

      • visiblebooleanRequired

        Whether the model is currently shown in the scene.

      • has_supportsbooleanRequired

        Whether support structures have been generated for the model.

      • is_groupbooleanRequired

        Whether this entry is a Part Group container rather than a regular printable model. Group containers have zero volume and an empty bounding box.

      • is_cagebooleanRequired

        Whether the group is a cage. Cages are a subset of groups, so is_cage: true implies is_group: true.

      • in_boundsbooleanRequired

        Whether the model lies entirely within the build volume.

      • raw_mesh_hashstringRequired

        Hash of the raw mesh data, before any transform.

      • canonical_model_hashstringRequired

        Hash of the mesh data together with its position, orientation, and scale.

      • lockenum LockRequired

        Orientation and position constraints on a model, respected by automatic layout and packing operations.

        Defaults to "FREE"

        Currently one of the following; more may be added:

        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.
    • scene_settingsSceneTypeRequired

      The machine/material/print-setting/layer-thickness combination used to create the scene.

      Show child attributes
      • machine_typestringRequired

        Canonical machine type id, e.g. "FORM-4-0".

      • material_codestringRequired

        Versioned material code, e.g. "FLGPBK05".

      • print_settingstringRequired

        Print setting profile code, e.g. "DEFAULT".

      • layer_thickness_mmstringRequired

        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/, whose layer_thickness_mm is 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 UnknownMaterialUsageRequired

      Material 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 2

        Material usage for an SLA-type scene (e.g. Form 4).

        Show fields
        • volume_mlnumberRequired

          Total volume of models and supports in the scene, in milliliters.

        • unsupported_volume_mlnumberRequired

          Total volume of models alone, not including supports, in milliliters.

      • SlsMaterialUsageoption 2 of 2

        Material usage for an SLS-type scene (e.g. Fuse 1+, Fuse X1).

        Show fields
        • total_powder_mlnumberRequired

          Total volume of powder used, including unsintered support powder, in milliliters.

        • total_powder_kgnumberRequired

          Total mass of powder used, including unsintered support powder, in kilograms.

        • total_sintered_powder_mlnumberRequired

          Volume of powder that ends up sintered (part of the finished print), in milliliters.

        • total_sintered_powder_kgnumberRequired

          Mass of powder that ends up sintered (part of the finished print), in kilograms.

        • mass_packing_densitynumberRequired

          Ratio of sintered powder mass to the total build volume.

    • layer_countintegerRequired

      Number of layers the scene would slice to.

    • build_volumeBuildVolumeRequired

      The build volume geometry for the scene's printer and material.

      Show child attributes
      • dimensions_mmobjectRequired

        Build volume size in millimeters.

        Show child attributes
        • xnumberRequired
        • ynumberRequired
        • znumberRequired
      • fillet_radius_mmnumberRequired

        Radius of the build volume's corner fillets, in millimeters.

The current scenes.

GET/v1/scene/list/
Python
from formlabs_sdk import FormlabsClient

with FormlabsClient() as client:
    preform = client.preform.connect()
    result = preform.list_scenes()
Terminal
curl "http://localhost:44388/v1/scene/list/"
Response
JSON
{
  "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#

HTTPerror.codeCause
400JSON_PARSE_ERRORThe request body is not a valid JSON object.
400MISSING_PARAMETERThe body has no scene_id field.
400INPUT_ERRORscene_id is not a well-formed UUID, or no scene with that id exists.

Request bodyobject

  • scene_idstring (uuid)Required

    The id of the scene to fetch.

ReturnsScene

  • idstring (uuid)Required

    Unique identifier of the scene.

  • modelsarray of ModelPropertiesRequired

    The models currently in the scene.

    Show child attributes
    • idstring (uuid)Required

      Unique identifier of the model within its scene.

    • namestringRequired

      Display name used within job preparation.

    • positionScenePositionRequired

      A position within a printer's build volume, in millimeters, in user coordinate space.

      Show child attributes
      • xnumberRequired

        X position. 0 is the center of the build volume. Positive moves right as you face the printer.

      • ynumberRequired

        Y position. 0 is the center of the build volume. Positive moves away from you as you face the printer.

      • znumberRequired

        Vertical position. 0 is the surface of the build platform.

    • orientationEulerAnglesRequired

      Orientation as Euler angles in degrees. Rotations are applied in the order z, then x, then y.

      Show child attributes
      • xnumberRequired

        Rotation in degrees around the x axis (applied second).

      • ynumberRequired

        Rotation in degrees around the y axis (applied last).

      • znumberRequired

        Rotation in degrees around the z axis (applied first).

    • scalenumberRequired

      Scale factor applied to the model.

    • unitsenum UnitsRequired

      The measurement units a model was defined in.

      Currently one of the following; more may be added:

      MILLIMETERS
      Model coordinates are millimeters.
      INCHES
      Model coordinates are inches.
    • bounding_boxobjectRequired

      Axis-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_cornerScenePosition

        A position within a printer's build volume, in millimeters, in user coordinate space.

        Show child attributes
        • xnumberRequired

          X position. 0 is the center of the build volume. Positive moves right as you face the printer.

        • ynumberRequired

          Y position. 0 is the center of the build volume. Positive moves away from you as you face the printer.

        • znumberRequired

          Vertical position. 0 is the surface of the build platform.

      • max_cornerScenePosition

        A position within a printer's build volume, in millimeters, in user coordinate space.

        Show child attributes
        • xnumberRequired

          X position. 0 is the center of the build volume. Positive moves right as you face the printer.

        • ynumberRequired

          Y position. 0 is the center of the build volume. Positive moves away from you as you face the printer.

        • znumberRequired

          Vertical position. 0 is the surface of the build platform.

    • original_filestringRequired

      Path of the file the model was imported from.

    • visiblebooleanRequired

      Whether the model is currently shown in the scene.

    • has_supportsbooleanRequired

      Whether support structures have been generated for the model.

    • is_groupbooleanRequired

      Whether this entry is a Part Group container rather than a regular printable model. Group containers have zero volume and an empty bounding box.

    • is_cagebooleanRequired

      Whether the group is a cage. Cages are a subset of groups, so is_cage: true implies is_group: true.

    • in_boundsbooleanRequired

      Whether the model lies entirely within the build volume.

    • raw_mesh_hashstringRequired

      Hash of the raw mesh data, before any transform.

    • canonical_model_hashstringRequired

      Hash of the mesh data together with its position, orientation, and scale.

    • lockenum LockRequired

      Orientation and position constraints on a model, respected by automatic layout and packing operations.

      Defaults to "FREE"

      Currently one of the following; more may be added:

      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.
  • scene_settingsSceneTypeRequired

    The machine/material/print-setting/layer-thickness combination used to create the scene.

    Show child attributes
    • machine_typestringRequired

      Canonical machine type id, e.g. "FORM-4-0".

    • material_codestringRequired

      Versioned material code, e.g. "FLGPBK05".

    • print_settingstringRequired

      Print setting profile code, e.g. "DEFAULT".

    • layer_thickness_mmstringRequired

      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/, whose layer_thickness_mm is 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 UnknownMaterialUsageRequired

    Material 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 2

      Material usage for an SLA-type scene (e.g. Form 4).

      Show fields
      • volume_mlnumberRequired

        Total volume of models and supports in the scene, in milliliters.

      • unsupported_volume_mlnumberRequired

        Total volume of models alone, not including supports, in milliliters.

    • SlsMaterialUsageoption 2 of 2

      Material usage for an SLS-type scene (e.g. Fuse 1+, Fuse X1).

      Show fields
      • total_powder_mlnumberRequired

        Total volume of powder used, including unsintered support powder, in milliliters.

      • total_powder_kgnumberRequired

        Total mass of powder used, including unsintered support powder, in kilograms.

      • total_sintered_powder_mlnumberRequired

        Volume of powder that ends up sintered (part of the finished print), in milliliters.

      • total_sintered_powder_kgnumberRequired

        Mass of powder that ends up sintered (part of the finished print), in kilograms.

      • mass_packing_densitynumberRequired

        Ratio of sintered powder mass to the total build volume.

  • layer_countintegerRequired

    Number of layers the scene would slice to.

  • build_volumeBuildVolumeRequired

    The build volume geometry for the scene's printer and material.

    Show child attributes
    • dimensions_mmobjectRequired

      Build volume size in millimeters.

      Show child attributes
      • xnumberRequired
      • ynumberRequired
      • znumberRequired
    • fillet_radius_mmnumberRequired

      Radius of the build volume's corner fillets, in millimeters.

The scene's current state.

POST/v1/scene/get/
Python
from formlabs_sdk import FormlabsClient

with FormlabsClient() as client:
    preform = client.preform.connect()
    result = preform.get_scene(
        scene_id="3fa85f64-5717-4562-b3fc-2c963f66afa6",
    )
Terminal
curl -X POST "http://localhost:44388/v1/scene/get/" \
  -H "Content-Type: application/json" \
  -d '{
    "scene_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
  }'
Response
JSON
{
  "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#

HTTPerror.codeCause
400JSON_PARSE_ERRORThe request body is not a valid JSON object.
400MISSING_PARAMETERThe body has no scene_id field.
400INPUT_ERRORscene_id is not a well-formed UUID, or no scene with that id exists.

Request bodyobject

  • scene_idstring (uuid)Required

    The 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.

    DELETE/v1/scene/delete/
    Python
    from formlabs_sdk import FormlabsClient
    
    with FormlabsClient() as client:
        preform = client.preform.connect()
        preform.delete_scene(
            scene_id="9b1dd8a0-4f6e-45c2-9a3e-77a01f2b6c55",
        )
    Terminal
    curl -X DELETE "http://localhost:44388/v1/scene/delete/" \
      -H "Content-Type: application/json" \
      -d '{
        "scene_id": "9b1dd8a0-4f6e-45c2-9a3e-77a01f2b6c55"
      }'
    Response
    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#

    HTTPerror.codeCause
    400JSON_PARSE_ERRORThe request body is not a valid JSON object.
    400JSON_SCHEMA_MATCH_ERRORThe 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.
    400INPUT_ERRORAn 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.
    400INVALID_QUERY_PARAMETERasync is present but not true or false.

    Query parameters

    • asyncboolean

      When true, returns 202 Accepted immediately with the operation's id and its operation_url to poll for the result, instead of blocking until the operation completes.

      Defaults to false

    Request bodySaveSceneRequest

    • filestringRequired

      Path to write the .form file to.

      At least 1 characters.

    • scene_idsarray of string (uuid)sRequired

      Ids 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.

      At least 1 items.

    • project_namestring

      Name 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)Required

        Randomly generated id of the tracked operation.

      • operation_urlstringRequired

        Server-relative URL of this operation's record: /v1/operation/get/?operation_id=<operation_id>. GET it to follow progress and retrieve the result.

      • messagestringRequired

        Human-readable pointer to where the result will appear. Purely informational. Use operation_url programmatically.

      The file was accepted for asynchronous saving (?async=true). Poll the operations endpoints with the returned id.

      Response headers (202)

      • Locationstring

        Server-relative URL of the accepted operation's record, identical to the response body's operation_url. GET it to follow progress and retrieve the result.

      POST/v1/scene/save/
      Python
      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"],
          )
      Terminal
      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"
          ]
        }'
      Python
      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"],
          )
      Terminal
      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"
          ]
        }'
      Response
      No response body.
      JSON
      {
        "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#

      HTTPerror.codeCause
      400JSON_PARSE_ERRORThe request body is not a valid JSON object.
      400JSON_SCHEMA_MATCH_ERRORThe 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.
      400INPUT_ERRORscene_id is not a well-formed UUID, no scene with that id exists, or file ends in .png while flyaround_transform is present.
      400INVALID_QUERY_PARAMETERasync is present but not true or false.
      400OPERATION_FAILEDview_type is ZOOM_ON_MODELS and no selected models are visible, or the render could not be written to file.
      404NOT_FOUNDA model in model_ids does not exist in the scene.

      Query parameters

      • asyncboolean

        When true, returns 202 Accepted immediately with the operation's id and its operation_url to poll for the result, instead of blocking until the operation completes.

        Defaults to false

      Request bodyRenderRequest

      • scene_idstring (uuid)Required

        The id of the scene to render.

      • filestringRequired

        Path to save the rendered image to. Must end in .png or .webp. .webp is required when flyaround_transform is present.

        Matches `^.*\.(png|webp)$`.

      • model_idsarray of string (uuid)s

        Ids of the models to make visible in the render (and candidates for ZOOM_ON_MODELS framing). Omitted or [] means every model in the scene.

        Defaults to []

      • Camera framing for a render.

        Defaults to "ZOOM_ON_MODELS"

        One of:

        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_pxinteger

        Maximum image width/height, in pixels. The render is square.

        Defaults to 820

      • crop_to_modelsboolean

        Whether to crop the frame tightly around the visible models instead of leaving margin.

        Defaults to true

      • yawnumber

        Camera yaw, in degrees. Ignored when flyaround_transform.transform is present.

        Defaults to 45

      • pitchnumber

        Camera pitch, in degrees. Ignored when flyaround_transform.transform is present.

        Defaults to 35.264

      • flyaround_transformany

        Renders a .webp animation instead of a single .png. Provide either an explicit transform keyframe list, or frame_count to auto-generate evenly-spaced frames around a full turn starting from the top-level yaw/pitch. At least one of the two is required.

        Show child attributes
        • transformarray of FlyaroundKeyframes

          Explicit list of camera keyframes to render, one per animation frame.

          At least 2 items.

          Show child attributes
          • yawnumberRequired

            Camera yaw for this frame, in degrees.

          • pitchnumberRequired

            Camera pitch for this frame, in degrees.

        • frame_countinteger

          Number of evenly-spaced frames to render around a full 360-degree turn. Ignored if transform is present.

          At least 1.

        • ensure_constant_sizeboolean

          When true, every frame is rendered at the same size (the largest needed by any frame) instead of each frame being cropped independently.

          Defaults to true

      Returns 200 OKno body

        The image was saved. The response has no body.

        Returns 202 AcceptedOperationAccepted

        • operation_idstring (uuid)Required

          Randomly generated id of the tracked operation.

        • operation_urlstringRequired

          Server-relative URL of this operation's record: /v1/operation/get/?operation_id=<operation_id>. GET it to follow progress and retrieve the result.

        • messagestringRequired

          Human-readable pointer to where the result will appear. Purely informational. Use operation_url programmatically.

        The render was accepted for asynchronous processing (?async=true). Poll the operations endpoints with the returned id.

        Response headers (202)

        • Locationstring

          Server-relative URL of the accepted operation's record, identical to the response body's operation_url. GET it to follow progress and retrieve the result.

        POST/v1/scene/render/
        Python
        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,
            )
        Terminal
        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
          }'
        Python
        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,
                },
            )
        Terminal
        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
            }
          }'
        Python
        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,
                        }],
                },
            )
        Terminal
        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
                }
              ]
            }
          }'
        Response
        No response body.
        JSON
        {
          "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#

        HTTPerror.codeCause
        400JSON_PARSE_ERRORThe request body is not a valid JSON object.
        400MISSING_PARAMETERThe body has no scene_id field.
        400INPUT_ERRORscene_id is not a well-formed UUID, or no scene with that id exists.
        400OPERATION_FAILEDThe estimation task could not run (e.g. the scene was deleted while the request was in flight).
        422ESTIMATION_NOT_SUPPORTEDThe scene's machine type does not support fast print time estimation.

        Request bodyobject

        • scene_idstring (uuid)Required

          The id of the scene to estimate.

        Returnsobject

        • total_print_time_sintegerRequired

          Estimated total print time, in seconds.

        The estimated total print time.

        POST/v1/scene/estimate-print-time/
        Python
        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",
            )
        Terminal
        curl -X POST "http://localhost:44388/v1/scene/estimate-print-time/" \
          -H "Content-Type: application/json" \
          -d '{
            "scene_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
          }'
        Response
        JSON
        {
          "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#

        HTTPerror.codeCause
        400JSON_PARSE_ERRORThe request body is not a valid JSON object.
        400MISSING_PARAMETERThe body has no scene_id field.
        400INPUT_ERRORscene_id is not a well-formed UUID, or no scene with that id exists.
        400INVALID_QUERY_PARAMETERasync is present but not true or false.
        400OPERATION_FAILEDThe print time calculation could not complete for this scene.

        Query parameters

        • asyncboolean

          When true, returns 202 Accepted immediately with the operation's id and its operation_url to poll for the result, instead of blocking until the operation completes.

          Defaults to false

        Request bodyobject

        • scene_idstring (uuid)Required

          The id of the scene to calculate print time for.

        Returns 200 OKobject

        • total_print_time_sintegerRequired

          Total print time in seconds, including pre-print time and, for Fuse 1+ scenes, cooling time.

        • preprint_time_sintegerRequired

          Time spent on pre-print steps (e.g. heating the tank), in seconds.

        • printing_time_sintegerRequired

          Time spent actively printing, in seconds.

        • cool_to_removal_time_sinteger

          Fuse 1+ scenes only. Time to cool the print to a safe removal temperature, in seconds.

        • additional_cool_to_room_temp_time_sinteger

          Fuse 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)Required

          Randomly generated id of the tracked operation.

        • operation_urlstringRequired

          Server-relative URL of this operation's record: /v1/operation/get/?operation_id=<operation_id>. GET it to follow progress and retrieve the result.

        • messagestringRequired

          Human-readable pointer to where the result will appear. Purely informational. Use operation_url programmatically.

        The calculation was accepted for asynchronous processing (?async=true). Poll the operations endpoints with the returned id.

        Response headers (202)

        • Locationstring

          Server-relative URL of the accepted operation's record, identical to the response body's operation_url. GET it to follow progress and retrieve the result.

        POST/v1/scene/calculate-print-time/
        Python
        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",
            )
        Terminal
        curl -X POST "http://localhost:44388/v1/scene/calculate-print-time/" \
          -H "Content-Type: application/json" \
          -d '{
            "scene_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
          }'
        Response
        JSON
        {
          "total_print_time_s": 420,
          "preprint_time_s": 120,
          "printing_time_s": 300
        }
        JSON
        {
          "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
        }
        JSON
        {
          "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#

        HTTPerror.codeCause
        400JSON_PARSE_ERRORThe request body is not a valid JSON object.
        400JSON_SCHEMA_MATCH_ERRORThe 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.
        400INPUT_ERRORscene_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 2

          A new machine/material/print-setting/layer-thickness combination to apply to the scene.

          Show fields
          • scene_idstring (uuid)Required

            The id of the scene to update.

          • machine_typestringRequired

            Canonical machine type id, e.g. "FORM-4-0".

          • material_codestringRequired

            Versioned material code, e.g. "FLGPBK05".

          • print_settingstring

            Print setting profile code, e.g. "DEFAULT".

          • layer_thickness_mmnumber or stringRequired

            A 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 2

          Update a scene from a saved .fps print settings file. Custom print settings are persisted so the scene's scene_settings.custom_print_setting_id can identify them later.

          Show fields
          • scene_idstring (uuid)Required

            The id of the scene to update.

          • fps_filestringRequired

            Full path to the .fps file.

        Returnsobject

        • scene_settingsSceneTypeRequired

          The machine/material/print-setting/layer-thickness combination used to create the scene.

          Show child attributes
          • machine_typestringRequired

            Canonical machine type id, e.g. "FORM-4-0".

          • material_codestringRequired

            Versioned material code, e.g. "FLGPBK05".

          • print_settingstringRequired

            Print setting profile code, e.g. "DEFAULT".

          • layer_thickness_mmstringRequired

            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/, whose layer_thickness_mm is 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.

        POST/v1/scene/update/
        Python
        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,
            )
        Terminal
        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
          }'
        Python
        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",
            )
        Terminal
        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"
          }'
        Response
        JSON
        {
          "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#

        HTTPerror.codeCause
        400INVALID_QUERY_PARAMETERasync is present but not true or false.
        400JSON_PARSE_ERRORThe request body is not a valid JSON object.
        400JSON_SCHEMA_MATCH_ERRORscene_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.
        400INPUT_ERRORscene_id is not a well-formed UUID, or no scene with that id exists.
        400OPERATION_FAILEDThe 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

        • asyncboolean

          When true, returns 202 Accepted immediately with the operation's id and its operation_url to poll for the result, instead of blocking until the operation completes.

          Defaults to false

        Request bodyPrintSceneRequest

        • scene_idstring (uuid)Required

          The id of the scene to print.

        • printerstringRequired

          Printer serial name, IP address, or Fleet Control Queue id.

        • job_namestringRequired

          Name of the job.

        • find_printer_timeout_secondsinteger

          Number of seconds to wait to find the given printer.

          At least 0.

          Defaults to 30

        • print_nowboolean

          If true, the job must print immediately. This fails with OPERATION_FAILED if the printer's ready_to_print_now status 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 current ready_to_print_now state: prints immediately if ready, queues otherwise.

        Returns 200 OKobject

        • job_idstring (uuid)Required

          The id of the newly created print job.

        The job was uploaded to the printer.

        Returns 202 AcceptedOperationAccepted

        • operation_idstring (uuid)Required

          Randomly generated id of the tracked operation.

        • operation_urlstringRequired

          Server-relative URL of this operation's record: /v1/operation/get/?operation_id=<operation_id>. GET it to follow progress and retrieve the result.

        • messagestringRequired

          Human-readable pointer to where the result will appear. Purely informational. Use operation_url programmatically.

        The request was accepted for asynchronous processing (?async=true). Poll the operations endpoints with the returned id.

        Response headers (202)

        • Locationstring

          Server-relative URL of the accepted operation's record, identical to the response body's operation_url. GET it to follow progress and retrieve the result.

        POST/v1/scene/print/
        Python
        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",
            )
        Terminal
        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"
          }'
        Python
        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,
            )
        Terminal
        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
          }'
        Response
        JSON
        {
          "job_id": "9c858901-8a57-4791-81fe-4c455b099bc9"
        }
        JSON
        {
          "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#

        HTTPerror.codeCause
        400JSON_PARSE_ERRORThe request body is not a valid JSON object.
        400MISSING_PARAMETERThe body has no scene_id field.
        400INPUT_ERRORscene_id is not a well-formed UUID, or no scene with that id exists.
        400OPERATION_FAILEDThe metadata could not be computed (e.g. the scene was deleted while the request was in flight).

        Request bodyobject

        • scene_idstring (uuid)Required

          The id of the scene.

        Returnsobject

          The scene's print-job metadata.

          POST/v1/scene/metadata/
          Python
          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",
              )
          Terminal
          curl -X POST "http://localhost:44388/v1/scene/metadata/" \
            -H "Content-Type: application/json" \
            -d '{
              "scene_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
            }'
          Response
          JSON
          {
            "MaterialCode": "FLGPGR05",
            "AllowedMachineTypeIds": [
              "FORM-4-0"
            ]
          }
          Feedback & Bug Reports