Formlabs Developers
Download PreForm Insider to start developing with the PreForm API.
Version v1.0.0-alpha (latest)

Printability Checks

Scene printability checks. These endpoints analyze the scene and report problems. They never modify it.

Detect cups#

POST/v1/scene/model/validate/cups/

Analyze every printable model in the scene for cups: cavities that face the build platform and seal against the resin surface as the part prints. Cups trap air or resin, causing suction forces during peel that lead to print failure, and trapped uncured resin in the finished part.

The check runs per model and returns the number of cups found in each. A cup_count of 0 means the model's current orientation produces no cups. To fix a model with cups, reorient it (manually or with /v1/scene/model/auto-orient/) or add drain holes (/v1/scene/model/drill/).

The whole scene is always analyzed. There is no model selection for this endpoint. Detection can take tens of seconds on complex scenes, so prefer ?async=true and poll the returned operation.

This endpoint reads the scene without modifying it. It is a POST because its input travels in the request body. The body carries only the scene reference.

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 detection task itself failed. 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 bodyobject

  • scene_idstring (uuid)Required

    The id of the scene to analyze.

Returns 200 OKobject

  • per_model_resultsmap of CupDetectionResultRequired

    Map of model id to that model's cup-detection result.

    Show child attributes
    • cup_countintegerRequired

      Number of cup cavities detected in the model's current orientation. 0 means no suction risk from cups.

      At least 0.

Detection completed. One entry per printable model in the scene, keyed by model id. An empty per_model_results means the scene contains no printable models.

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.

Detection started asynchronously (?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/model/validate/cups/
Python
from formlabs_sdk import FormlabsClient

with FormlabsClient() as client:
    preform = client.preform.connect()
    result = preform.validate_cups(
        scene_id="3fa85f64-5717-4562-b3fc-2c963f66afa6",
    )
Terminal
curl -X POST "http://localhost:44388/v1/scene/model/validate/cups/" \
  -H "Content-Type: application/json" \
  -d '{
    "scene_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
  }'
Response
JSON
{
  "per_model_results": {
    "c2a37eb2-8e4b-4b8e-9f37-1f5f2c1a9d10": {
      "cup_count": 0
    },
    "9b1dd8a0-4f6e-45c2-9a3e-77a01f2b6c55": {
      "cup_count": 2
    }
  }
}
JSON
{
  "per_model_results": {}
}
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."
}

Detect unsupported minima#

POST/v1/scene/model/validate/minima/

Analyze every printable model in the scene for unsupported minima: local low points on the surface that the model's current supports don't reach. Unsupported minima may break off the part during printing and lead to print failures.

The check runs per model and returns the number of unsupported minima found in each. A minima_count of 0 means every low point on the model is currently supported. To fix a model with minima, add supports manually or regenerate them (/v1/scene/model/auto-support/).

The whole scene is always analyzed. There is no model selection for this endpoint. Detection can take tens of seconds on complex 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.
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 detection task itself failed. 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 bodyobject

  • scene_idstring (uuid)Required

    The id of the scene to analyze.

Returns 200 OKobject

  • per_model_resultsmap of MinimaDetectionResultRequired

    Map of model id to that model's minima-detection result.

    Show child attributes
    • minima_countintegerRequired

      Number of unsupported local minima detected on the model. 0 means every low point is currently supported.

      At least 0.

Detection completed. One entry per printable model in the scene, keyed by model id. An empty per_model_results means the scene contains no printable models.

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.

Detection started asynchronously (?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/model/validate/minima/
Python
from formlabs_sdk import FormlabsClient

with FormlabsClient() as client:
    preform = client.preform.connect()
    result = preform.validate_minima(
        scene_id="3fa85f64-5717-4562-b3fc-2c963f66afa6",
    )
Terminal
curl -X POST "http://localhost:44388/v1/scene/model/validate/minima/" \
  -H "Content-Type: application/json" \
  -d '{
    "scene_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
  }'
Response
JSON
{
  "per_model_results": {
    "c2a37eb2-8e4b-4b8e-9f37-1f5f2c1a9d10": {
      "minima_count": 0
    },
    "9b1dd8a0-4f6e-45c2-9a3e-77a01f2b6c55": {
      "minima_count": 3
    }
  }
}
JSON
{
  "per_model_results": {}
}
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."
}

Detect undersupported area#

POST/v1/scene/model/validate/supportedness/

Analyze every printable model in the scene for how much of its surface is undersupported. This is the same calculation behind the desktop app's "Undersupported Models" red-shading toggle.

The check runs per model and returns percent_unsupported, on a 0-100 scale. 0 means the model is fully supported in its current orientation and support configuration. Higher values mean more of the surface is at risk of printing incompletely or breaking off during the print.

The whole scene is always analyzed. There is no model selection for this endpoint. Detection can take tens of seconds on complex 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.
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 detection task itself failed. 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 bodyobject

  • scene_idstring (uuid)Required

    The id of the scene to analyze.

Returns 200 OKobject

  • per_model_resultsmap of SupportednessDetectionResultRequired

    Map of model id to that model's supportedness-detection result.

    Show child attributes
    • percent_unsupportednumberRequired

      Percentage of the model's surface that is undersupported in its current orientation and support configuration. 0 means fully supported.

      At least 0, at most 100.

Detection completed. One entry per printable model in the scene, keyed by model id. An empty per_model_results means the scene contains no printable models.

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.

Detection started asynchronously (?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/model/validate/supportedness/
Python
from formlabs_sdk import FormlabsClient

with FormlabsClient() as client:
    preform = client.preform.connect()
    result = preform.validate_supportedness(
        scene_id="3fa85f64-5717-4562-b3fc-2c963f66afa6",
    )
Terminal
curl -X POST "http://localhost:44388/v1/scene/model/validate/supportedness/" \
  -H "Content-Type: application/json" \
  -d '{
    "scene_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
  }'
Response
JSON
{
  "per_model_results": {
    "c2a37eb2-8e4b-4b8e-9f37-1f5f2c1a9d10": {
      "percent_unsupported": 0
    },
    "9b1dd8a0-4f6e-45c2-9a3e-77a01f2b6c55": {
      "percent_unsupported": 42.5
    }
  }
}
JSON
{
  "per_model_results": {}
}
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."
}

Detect thin walls#

POST/v1/scene/model/validate/thin-features/

Analyze the selected models for walls thinner than threshold_mm: regions likely to be fragile, warp, or fail to cure fully during printing.

Unlike the other printability-check endpoints, this one takes an explicit model selection (model_ids) and a required threshold, rather than always scanning every printable model in the scene. Omitting model_ids (or passing an empty array) analyzes every model currently in the scene, including non-printable ones.

The check runs per model and returns an aggregate summary (has_thin_walls, thin_volume_mm3, thin_region_count) plus, when thin walls were found, a thin_regions breakdown of each connected thin region's volume and bounding box.

Detection can take a while on complex scenes or a large model selection, 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 is missing, threshold_mm is missing or not a positive number, model_ids is present but not an array of strings, or an unrecognized field is present.
400INPUT_ERRORscene_id is not a well-formed UUID, or no scene with that id exists.
400OPERATION_FAILEDThe detection task failed, including when model_ids names an id that does not exist in the scene. 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 bodyThinWallDetectionRequest

  • scene_idstring (uuid)Required

    The id of the scene containing the models.

  • model_idsarray of string (uuid)s

    Ids of the models to analyze. Omitted or empty means every model in the scene, including non-printable ones.

  • threshold_mmnumberRequired

    Wall thickness threshold, in millimeters. Regions thinner than this are flagged as thin.

    Greater than 0.

Returns 200 OKobject

  • per_model_resultsmap of ThinWallDetectionResultRequired

    Map of model id to that model's thin-wall-detection result.

    Show child attributes
    • statusstringRequired

      Per-model analysis outcome. ANALYZED: analysis ran (see the other fields). TOO_SMALL: too small/thin to voxelize (sub-~2-voxel extent or sub-voxel shell). TOO_LARGE: too large to voxelize within the memory budget at this resolution (often a units mistake). MESH_ERROR: the mesh could not be rasterized (degenerate/broken geometry). For any non-ANALYZED status the model could not be assessed: has_thin_walls is false and thin_regions is empty. These are per-model outcomes, not request errors, and other models still return normally.

      One of:

      ANALYZED
       
      TOO_SMALL
       
      TOO_LARGE
       
      MESH_ERROR
       
    • has_thin_wallsbooleanRequired

      Whether any thin region was found.

    • thin_volume_mm3numberRequired

      Sum of all detected thin regions' volumes, in cubic millimeters. 0 if has_thin_walls is false.

    • thin_region_countintegerRequired

      Number of distinct thin regions detected, equal to the length of thin_regions.

      At least 0.

    • thin_regionsarray of objectsRequired

      Per-region breakdown, sorted by volume descending. Empty if has_thin_walls is false.

      Show child attributes
      • volume_mm3numberRequired

        Volume of this connected thin region, in cubic millimeters.

      • bounding_boxobjectRequired

        Axis-aligned bounding box of the region, in scene coordinates.

        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.

Detection completed. One entry per analyzed model, keyed by model id. An empty per_model_results means the scene (or the requested model_ids) contains no models.

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.

Detection started asynchronously (?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/model/validate/thin-features/
Python
from formlabs_sdk import FormlabsClient

with FormlabsClient() as client:
    preform = client.preform.connect()
    result = preform.validate_thin_features(
        scene_id="3fa85f64-5717-4562-b3fc-2c963f66afa6",
        threshold_mm=0.5,
    )
Terminal
curl -X POST "http://localhost:44388/v1/scene/model/validate/thin-features/" \
  -H "Content-Type: application/json" \
  -d '{
    "scene_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "threshold_mm": 0.5
  }'
Python
from formlabs_sdk import FormlabsClient

with FormlabsClient() as client:
    preform = client.preform.connect()
    result = preform.validate_thin_features(
        scene_id="3fa85f64-5717-4562-b3fc-2c963f66afa6",
        model_ids=["c2a37eb2-8e4b-4b8e-9f37-1f5f2c1a9d10", "9b1dd8a0-4f6e-45c2-9a3e-77a01f2b6c55"],
        threshold_mm=0.6,
    )
Terminal
curl -X POST "http://localhost:44388/v1/scene/model/validate/thin-features/" \
  -H "Content-Type: application/json" \
  -d '{
    "scene_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "model_ids": [
      "c2a37eb2-8e4b-4b8e-9f37-1f5f2c1a9d10",
      "9b1dd8a0-4f6e-45c2-9a3e-77a01f2b6c55"
    ],
    "threshold_mm": 0.6
  }'
Response
JSON
{
  "per_model_results": {
    "c2a37eb2-8e4b-4b8e-9f37-1f5f2c1a9d10": {
      "status": "ANALYZED",
      "has_thin_walls": false,
      "thin_volume_mm3": 0,
      "thin_region_count": 0,
      "thin_regions": []
    },
    "9b1dd8a0-4f6e-45c2-9a3e-77a01f2b6c55": {
      "status": "ANALYZED",
      "has_thin_walls": true,
      "thin_volume_mm3": 12.4,
      "thin_region_count": 2,
      "thin_regions": [
        {
          "volume_mm3": 9.1,
          "bounding_box": {
            "min_corner": {
              "x": -10,
              "y": -5,
              "z": 0
            },
            "max_corner": {
              "x": -6,
              "y": 5,
              "z": 3
            }
          }
        },
        {
          "volume_mm3": 3.3,
          "bounding_box": {
            "min_corner": {
              "x": 4,
              "y": -2,
              "z": 8
            },
            "max_corner": {
              "x": 7,
              "y": 2,
              "z": 10
            }
          }
        }
      ]
    }
  }
}
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."
}

Detect colliding models#

POST/v1/scene/model/validate/interferences/

Find pairs of models in the scene that overlap by more than the collision-detection offset. Models scaled, moved, or reoriented without re-validating the layout (see /v1/scene/model/scale/, /v1/scene/model/translate/, and /v1/scene/model/orient/, each of which recommends calling this endpoint afterwards) may end up overlapping without any other feedback.

Every visible, printable model in the scene is considered. There is no model selection for this endpoint.

collision_offset_mm, an optional body field, overrides the scene's own configured visual collision offset for this call only. If it is absent, the scene's configured offset is used.

Unlike the other printability-check endpoints, this one does not support ?async=true: colliding-models detection always runs synchronously.

Error codes#

HTTPerror.codeCause
400JSON_PARSE_ERRORThe request body is not a valid JSON object.
400JSON_SCHEMA_MATCH_ERRORscene_id is missing, collision_offset_mm is not a number, or an unrecognized field is present.
400INPUT_ERRORscene_id is not a well-formed UUID, or no scene with that id exists.
400OPERATION_FAILEDThe detection task itself failed. The message carries the underlying reason.

Request bodyobject

  • scene_idstring (uuid)Required

    The id of the scene to analyze.

  • collision_offset_mmnumber

    Minimum gap, in millimeters, models must keep to not be reported as colliding. Negative values allow a controlled amount of overlap. Defaults to the scene's own configured visual collision offset.

Returnsobject

  • model_idsarray of array of string (uuid)sRequired

    Each entry is one colliding pair: a 2-element array of the two models' ids. A model can appear in more than one pair.

Detection completed. Empty model_ids means no colliding pairs were found.

POST/v1/scene/model/validate/interferences/
Python
from formlabs_sdk import FormlabsClient

with FormlabsClient() as client:
    preform = client.preform.connect()
    result = preform.validate_interferences(
        scene_id="3fa85f64-5717-4562-b3fc-2c963f66afa6",
    )
Terminal
curl -X POST "http://localhost:44388/v1/scene/model/validate/interferences/" \
  -H "Content-Type: application/json" \
  -d '{
    "scene_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
  }'
Python
from formlabs_sdk import FormlabsClient

with FormlabsClient() as client:
    preform = client.preform.connect()
    result = preform.validate_interferences(
        scene_id="3fa85f64-5717-4562-b3fc-2c963f66afa6",
        collision_offset_mm=0.5,
    )
Terminal
curl -X POST "http://localhost:44388/v1/scene/model/validate/interferences/" \
  -H "Content-Type: application/json" \
  -d '{
    "scene_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "collision_offset_mm": 0.5
  }'
Response
JSON
{
  "model_ids": [
    [
      "c2a37eb2-8e4b-4b8e-9f37-1f5f2c1a9d10",
      "9b1dd8a0-4f6e-45c2-9a3e-77a01f2b6c55"
    ]
  ]
}
JSON
{
  "model_ids": []
}

Check models are manifold#

POST/v1/scene/model/validate/manifoldness/

Validate that the selected models are manifold solids: closed, watertight meshes where every edge is shared by exactly two triangles. Non-manifold geometry (holes, open boundaries, bowtie vertices, self-inconsistent triangulation) can slice incorrectly and cause print failures.

The check runs per model using the manifold library and reports each model's verdict. A model that is not manifold can be repaired with /v1/scene/model/repair/.

Some operations require manifold input: /v1/scene/model/hollow/ and /v1/scene/model/drill/ do not work on non-manifold models (/v1/scene/model/dental-hollow/ is unaffected because it rebuilds the surface rather than operating on the input topology). Run this check, and repair if it fails, before relying on those endpoints.

Omitting model_ids checks every model in the scene. This endpoint reads the scene without modifying it, and is a POST only because its input travels in the request body.

Error codes#

HTTPerror.codeCause
400JSON_PARSE_ERRORThe request body is not a valid JSON object.
400JSON_SCHEMA_MATCH_ERRORThe body does not match the request schema: scene_id missing, a field has the wrong type, model_ids is present but not an array of strings, or an unknown field is present.
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 check itself failed. The message carries the underlying reason.
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 bodyCheckManifoldRequest

  • scene_idstring (uuid)Required

    The id of the scene containing the models.

  • model_idsarray of string (uuid)s

    Ids of the models to check. Omitted or empty means every model in the scene.

Returns 200 OKobject

  • per_model_resultsmap of ManifoldCheckResultRequired

    Map of model id to that model's manifold-check result.

    Show child attributes
    • is_manifoldbooleanRequired

      Whether the model's mesh is a manifold solid. Equivalent to status == "MANIFOLD".

    • The manifold library's verdict on a mesh. Only MANIFOLD means the mesh is a valid manifold solid.

      Currently one of the following; more may be added:

      MANIFOLD
      The mesh is a closed manifold solid.
      NOT_MANIFOLD
      The mesh has non-manifold geometry, such as open boundaries, holes, or edges/vertices shared inconsistently between triangles.
      NON_FINITE_VERTEX
      The mesh contains a vertex with a NaN or infinite coordinate.
      OTHER_ERROR
      The manifold library rejected the mesh for another reason.

The check completed. One entry per selected model, keyed by model id. An empty per_model_results means the selection matched no models.

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 check started asynchronously (?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/model/validate/manifoldness/
Python
from formlabs_sdk import FormlabsClient

with FormlabsClient() as client:
    preform = client.preform.connect()
    result = preform.validate_manifoldness(
        scene_id="3fa85f64-5717-4562-b3fc-2c963f66afa6",
    )
Terminal
curl -X POST "http://localhost:44388/v1/scene/model/validate/manifoldness/" \
  -H "Content-Type: application/json" \
  -d '{
    "scene_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
  }'
Python
from formlabs_sdk import FormlabsClient

with FormlabsClient() as client:
    preform = client.preform.connect()
    result = preform.validate_manifoldness(
        scene_id="3fa85f64-5717-4562-b3fc-2c963f66afa6",
        model_ids=["c2a37eb2-8e4b-4b8e-9f37-1f5f2c1a9d10"],
    )
Terminal
curl -X POST "http://localhost:44388/v1/scene/model/validate/manifoldness/" \
  -H "Content-Type: application/json" \
  -d '{
    "scene_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "model_ids": [
      "c2a37eb2-8e4b-4b8e-9f37-1f5f2c1a9d10"
    ]
  }'
Response
JSON
{
  "per_model_results": {
    "c2a37eb2-8e4b-4b8e-9f37-1f5f2c1a9d10": {
      "is_manifold": true,
      "status": "MANIFOLD"
    },
    "9b1dd8a0-4f6e-45c2-9a3e-77a01f2b6c55": {
      "is_manifold": false,
      "status": "NOT_MANIFOLD"
    }
  }
}
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."
}

Check models fit in the build volume#

POST/v1/scene/model/validate/in-bounds/

Report whether each selected model, at its current position, orientation and scale, fits inside the build volume of the scene's printer type.

This is a direct read of scene state, not a computation: it never reorients, rescales, moves or re-lays-out anything, and it does not report whether a model could fit in some other pose. A model that would fit if rotated is still reported in_bounds: false while it sticks out where it currently sits.

The verdict includes a model's supports, so adding supports can take an in-bounds model out of bounds. It is the same verdict as the in_bounds field of /v1/scene/model/list/; this endpoint exists so that callers whose only question is "does it fit?" can ask it directly rather than reading and filtering full model state.

Models out of the build volume are an ordinary, expected result here, reported as in_bounds: false with a 200. Unlike /v1/scene/model/validate/cups/ and /v1/scene/model/validate/minima/, this endpoint does not fail with OPERATION_FAILED when a model does not fit.

Omitting model_ids checks every model in the scene. This endpoint reads the scene without modifying it, and is a POST only because its input travels in the request body. The check is immediate, so there is no async form.

Error codes#

HTTPerror.codeCause
400JSON_PARSE_ERRORThe request body is not a valid JSON object.
400JSON_SCHEMA_MATCH_ERRORThe body does not match the request schema: scene_id missing, a field has the wrong type, model_ids is present but not an array of strings, or an unknown field is present.
400INPUT_ERRORscene_id is not a well-formed UUID, or no scene with that id exists.
404NOT_FOUNDA model in model_ids does not exist in the scene.

Request bodyInBoundsDetectionRequest

  • scene_idstring (uuid)Required

    The id of the scene containing the models.

  • model_idsarray of string (uuid)s

    Ids of the models to check. Omitted or empty means every model in the scene.

Returnsobject

  • per_model_resultsmap of InBoundsResultRequired

    Map of model id to that model's build-volume verdict.

    Show child attributes
    • in_boundsbooleanRequired

      Whether the model, including its supports, fits inside the build volume at its current position, orientation and scale. The same verdict as the in_bounds field of /v1/scene/model/list/.

  • all_in_boundsbooleanRequired

    Whether every selected model is in bounds. true when per_model_results is empty.

The check completed. One entry per selected model, keyed by model id. An empty per_model_results means the selection matched no models, in which case all_in_bounds is true.

POST/v1/scene/model/validate/in-bounds/
Python
from formlabs_sdk import FormlabsClient

with FormlabsClient() as client:
    preform = client.preform.connect()
    result = preform.validate_in_bounds(
        scene_id="3fa85f64-5717-4562-b3fc-2c963f66afa6",
    )
Terminal
curl -X POST "http://localhost:44388/v1/scene/model/validate/in-bounds/" \
  -H "Content-Type: application/json" \
  -d '{
    "scene_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
  }'
Python
from formlabs_sdk import FormlabsClient

with FormlabsClient() as client:
    preform = client.preform.connect()
    result = preform.validate_in_bounds(
        scene_id="3fa85f64-5717-4562-b3fc-2c963f66afa6",
        model_ids=["c2a37eb2-8e4b-4b8e-9f37-1f5f2c1a9d10"],
    )
Terminal
curl -X POST "http://localhost:44388/v1/scene/model/validate/in-bounds/" \
  -H "Content-Type: application/json" \
  -d '{
    "scene_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "model_ids": [
      "c2a37eb2-8e4b-4b8e-9f37-1f5f2c1a9d10"
    ]
  }'
Response
JSON
{
  "per_model_results": {
    "c2a37eb2-8e4b-4b8e-9f37-1f5f2c1a9d10": {
      "in_bounds": true
    },
    "9b1dd8a0-4f6e-45c2-9a3e-77a01f2b6c55": {
      "in_bounds": false
    }
  },
  "all_in_bounds": false
}
Feedback & Bug Reports