Quoting API — Digital Metal
Digital Metal

Quoting API

Quoting API

The pipeline that powers the public quote tool, exposed as plain HTTP. Convert a STEP into geometry data, fetch material + finishing options, compute a shell-pricing quote, and (if you want) place the order — all behind one X-API-Key header.

https://digitalmetal.io/api/v1

Pipeline at a glance

  1. GET /materials — pick a material UUID for your part.
  2. POST /convert — upload the STEP/glTF, receive volume / surface area / bbox + a base64 GLB for preview.
  3. (Optional) GET /post-processing — pick finishing services.
  4. POST /quotes — provide geometry + material + quantity, receive a full pricing breakdown.
  5. GET /quotes/:id — later, retrieve the same quote for follow-up.
POST

/convert

Upload a STEP / STP / glTF / GLB file. KittyCAD extracts volume, surface area, axis-aligned bounding box, and produces a renderable GLB. 25 MB file cap, 60-second timeout. Response is plain JSON; no async polling needed.

Request

curl -X POST https://digitalmetal.io/api/v1/convert \
  -H "X-API-Key: dm_live_<your_key>" \
  -F "file=@bracket.step"

Response 200

{
  "geometry": {
    "volume_cm3": 12.4503,
    "surface_area_cm2": 84.2011,
    "bounding_box": { "x_mm": 48.300, "y_mm": 32.100, "z_mm": 21.600 }
  },
  "glb_base64": "<base64-encoded GLB binary>"
}

Common errors

  • 400 — missing or invalid file field
  • 413 — file exceeds 25 MB
  • 422 — multi-body file (split + upload separately) / part exceeds 150 mm build volume / geometry not extractable

GET

/materials

Active casting materials. Use the returned UUID as material_id when creating a quote.

Response 200

{
  "materials": [
    {
      "id": "uuid",
      "name": "Aluminum A356",
      "description": "General-purpose casting alloy",
      "density_kg_m3": 2680,
      "cost_per_kg": 4.20,
      "maximum_part_size_mm": "150mm x 150mm x 150mm"
    }
  ]
}

GET

/post-processing

Active post-processing / finishing options. Each option carries pricing model + unit cost.

Response 200

{
  "post_processing_options": [
    {
      "id": "uuid",
      "name": "Bead blast",
      "description": "Uniform satin finish",
      "pricing_model": "per_part",
      "cost_per_unit": 4.50
    }
  ]
}

POST

/quotes

Generates a shell-pricing quote and persists it to your account. Geometry comes from /convert, the material UUID from /materials.

Request body (application/json)

{
  "file_name":   "bracket.step",
  "geometry":    { "volume_cm3": 12.45, "surface_area_cm2": 84.2,
                   "bounding_box": { "x_mm": 48.3, "y_mm": 32.1, "z_mm": 21.6 } },
  "material_id": "<uuid>",
  "quantity":    10,
  "post_processing_option_ids": ["<uuid>", "..."]   // optional
}

Response 200

{
  "quote": {
    "id": "uuid",
    "status": "draft",
    "unit_price":  18.42,
    "total_price": 184.20,
    "breakdown": {
      "metal_cost":  3.10,
      "shell_cost":  5.40,
      "labor_cost":  4.20,
      "post_processing_cost": 4.50,
      "margin":      1.22
    },
    "lead_time_days": 14
  }
}

GET

/quotes/:id

Retrieve a previously created quote. Response shape matches POST /quotes.

curl https://digitalmetal.io/api/v1/quotes/a1b2c3d4-... \
  -H "X-API-Key: dm_live_<your_key>"

End-to-end example

Convert → pick a material → price 10 parts:

# 1. extract geometry
curl -sS -X POST https://digitalmetal.io/api/v1/convert \
  -H "X-API-Key: $DM_KEY" -F "file=@bracket.step" > geom.json

# 2. pick the first material
curl -sS https://digitalmetal.io/api/v1/materials \
  -H "X-API-Key: $DM_KEY" | jq '.materials[0].id' > matid

# 3. quote
jq -n \
  --slurpfile g geom.json \
  --rawfile m matid \
  '{ file_name: "bracket.step", geometry: $g[0].geometry,
     material_id: ($m | rtrimstr("\n") | gsub("\""; "")), quantity: 10 }' \
  | curl -sS -X POST https://digitalmetal.io/api/v1/quotes \
      -H "X-API-Key: $DM_KEY" -H "Content-Type: application/json" -d @-

See also