# Pricing model

> How a print quote is computed at X3D: the all-in per-gram rate, the quality multiplier, gram rounding, bulk tiers, colour and the second-AMS fee, Priority print, support removal, and shipping, with a worked example.

Source: https://x3dstudios.com/docs/pricing  ·  Updated: 2026-10-20

A print is priced by weight. One all-in rate per gram covers the filament and the normal machine time, billable weight rounds up to the whole gram, and there is a $1.00 minimum per part. This page gives you the whole calculation, so you can work out your own quote before you upload anything.

## The formula

**One part, one order**

```text
billable grams = ceil(grams)
per part       = billable grams x rate per gram x quality factor
order subtotal = max(per part x quantity x bulk factor, $1.00 x quantity)
order total    = order subtotal + shipping + Priority print and support removal, if chosen
                 + $15 per spool bought in, unless the goods are over $100
```

Everything else on this page is either where the grams come from or which number goes into which slot. Nothing is added for setup, file handling, supports or brim — supports and brim are plastic, so they arrive as grams and are paid for as grams. Taking the supports off afterwards is optional: support removal, $10 once per order at checkout.

Three charges sit outside the per-gram part and only appear when they apply: the $25 second-AMS fee for a print in five or more colours, below; Priority print, $5 once per order if you choose it at checkout to have the order printed first; and support removal, $10 once per order if you choose to have the supports taken off before it ships. Normal print is included. None of them is discounted or counted toward free shipping. See /docs/studio/checkout.

Two discounts can come off that total at the till, and neither is part of the quote above. An account that has never paid us for anything takes 10% off the goods at cart checkout — postage excluded — and a gift card can be applied on top of it. A Pro account takes 10% off an order placed straight from /print with its Order button, postage included, and any print credit on the account then comes off what is left.

## Rate per gram

| Material | API key | Rate per gram | Density |
| --- | --- | --- | --- |
| PLA | pla | $0.12 | 1.26 g/cm³ |
| PETG | petg | $0.12 | 1.27 g/cm³ |
| ABS | abs | $0.12 | 1.04 g/cm³ |
| ASA | asa | $0.14 | 1.07 g/cm³ |
| Flexible TPU | tpu | $0.25 | 1.24 g/cm³ |

*All-in USD per gram — filament and normal machine time together.*

Density is part of the price, not a footnote. The same model in ABS weighs about 18% less than in PETG, so at the same $0.12/g it costs about 18% less to print. See /docs/materials for what each plastic is actually good for.

> **A colour we do not stock has a $0.20/g floor** — Twelve colours are held on the shelf and print at the rate above, as do the extra colours in our filament catalog while they are in stock. Any other colour is charged at a minimum of $0.20 per gram, because the spool has to be bought in for that order. It is a floor rather than an override, so a material that costs more than $0.20/g keeps its own rate: Flexible TPU is $0.25/g in any colour. Leaving the colour blank is not a custom order. On the website, a spool bought in also carries a $15 new-filament fee, once per different spool, and nothing when the goods come to more than $100.

A Custom filament, a spool you name on /print for us to buy in (API key custom on the quote API, with its name as customFilament), is $0.20 per gram for the same reason, plus the same $15 new-filament fee on the website (free over $100 of goods). Its grams are worked out at the density of the plastic the name states, and at PLA's 1.26 g/cm³ when it names none.

## Quality factor

| Quality | Layer height | Price factor | Effect on a $0.12/g material |
| --- | --- | --- | --- |
| Standard | 0.2 mm | 1.00 | $0.12 per gram |
| Premium | 0.1 mm | 1.75 | $0.21 per gram |

Premium halves the layer height, which roughly doubles the machine time for the same weight of plastic. The factor multiplies the per-gram charge; it does not add an hourly line.

## Where the grams come from

Two sources, and the quote says which one it used. Measured always beats modelled.

- Measured — the file is sliced by OrcaSlicer with the real Bambu profile for the farm's H2S, in the pose the farm prints it (an uploaded GLB lying the way the page shows it, with glTF's Y as up, unless the file was plainly written Z-up, when it stands on the flat base it was written with), and the filament volume it reports is converted to grams with the material's density. TPU is sliced on the farm's own TPU preset, the one it prints TPU with; the other plastics are measured on Bambu PLA Basic. This is what the quote uses wherever a slice can be run. It takes ten seconds to a minute, so the first number on the page may still be the estimate.
- Estimated — a geometric fallback used before a slice lands: model volume x (0.30 + 0.70 x infill), then x density. The 0.30 is the solid perimeter walls; infill fills the rest. Requested infill is clamped to 5–100% and defaults to 20%.
- A pre-sliced plate (a .3mf / .gcode.3mf plate export, or a .gcode sent to the print API) is always measured: the grams and hours come out of the file's own header, and they already contain every purge, support and brim.
- A print in colour is always measured too: a project or a generated model is sliced in its colours, and that slice's grams and hours are the price.

> **Checkout will not sell an unmeasured print** — The volume estimate undercounts thin, wall-heavy parts — one observed case slices at 21 g on the plate against a 12.9 g estimate — so charging from it would sell below the advertised rate. If a slice has not landed yet, cart checkout answers 409 with measuring: true and the cart holds the button closed until it has. Above 35% requested infill the quote stays on the estimate, because our slice runs at the profile's sparse default and stops representing what you asked for.

## Rounding and the minimum

- Billable weight rounds UP to the whole gram, like postage. 39.92 g bills as 40 g. Nothing is added before that rounding — the multi-colour purge surcharge the code can model is switched off, so it contributes nothing.
- $1.00 is the minimum per part. A 3 g PLA keychain works out at $0.36 and bills at $1.00. The floor is applied per unit, so ten of them floor at $10.00 and not $1.00.

## Worked example

A part measuring 60 x 40 x 30 mm, PLA, Standard quality, 20% infill, one unit, shipped in the US. Every step below is arithmetic you can repeat.

1. **Start from volume** — An uploaded mesh gives its real volume. This example uses the bounding box, which is what the quote API works from: 60 x 40 x 30 mm = 72,000 mm³ = 72 cm³.

```text
60 x 40 x 30 / 1000 = 72 cm3
```

2. **Apply walls and infill** — 30% of the volume is solid wall; the remaining 70% is filled to the requested infill.

```text
72 x (0.30 + 0.70 x 0.20) = 31.68 cm3
```

3. **Convert to weight** — Multiply by the density of PLA, 1.26 g/cm³.

```text
31.68 x 1.26 = 39.92 g
```

4. **Round up** — Billable weight is a whole number of grams.

```text
ceil(39.92) = 40 g
```

5. **Apply the rate and the quality factor** — PLA is $0.12/g and Standard quality is 1.00. This is above the $1.00 minimum, so the minimum does not bite.

```text
40 x 0.12 x 1.00 = $4.80 per part
```

6. **Multiply by quantity, then add shipping** — One unit gets no bulk discount, and US shipping is $7.00 flat below $49.50.

```text
4.80 x 1 x 1.00 = $4.80
4.80 + 7.00 = $11.80
```

You can check that against the quote API, which is public and needs no key.

`POST /api/price`

Quote a bounding box. No authentication, no rate limit, no order is created.

Auth: public

**Request body**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `bboxMm` | object | yes | Bounding box in millimetres as { x, y, z }. Each must be a finite number above 0. The three values are sorted before the build-volume check, so a long thin part that only fits rotated is still accepted. |
| `material` | string (pla \\| petg \\| abs \\| asa \\| tpu \\| custom) | no, default `pla` | Anything else is rejected with unknown material: <value>. custom is a filament you name, at $0.20/g. |
| `customFilament` | string | no | With material custom: the spool's name. The plastic it states sets the density; with none, PLA's is used. |
| `quality` | string (standard \\| premium) | no, default `standard` | Anything else is rejected with unknown quality: <value>. |
| `quantity` | number | no, default `1` | Rounded, and floored at 1. Bulk tiers are applied from this number. |
| `color` | string | no | A stock colour name or a hex value. Trimmed to 64 characters, and a value containing anything outside letters, digits, spaces and # ( ) , . _ - is discarded whole and quoted as no preference. Off-palette raises the per-gram rate to the $0.20 floor; tpu, already above it, stays at $0.25. |
| `shippingSpeed` | string (standard \\| express) | no, default `standard` | US postage in the quote: $7 standard or $15 express. Anything else is quoted as standard. |

**The example above, as a request**

```bash
curl -X POST https://x3dstudios.com/api/price \
  -H "Content-Type: application/json" \
  -d '{
    "bboxMm": { "x": 60, "y": 40, "z": 30 },
    "material": "pla",
    "quality": "standard",
    "quantity": 1,
    "color": "Black"
  }'
```

**200 response**

```json
{
  "filamentChanges": 0,
  "multiColorGrams": 0,
  "multiColorHours": 0,
  "grams": 40,
  "printHours": 1.98,
  "materialCost": 4.8,
  "machineCost": 0,
  "shipping": 7,
  "baseFee": 0,
  "perUnit": 4.8,
  "subtotal": 4.8,
  "total": 11.8,
  "currency": "USD",
  "material": "pla",
  "quality": "standard",
  "quantity": 1,
  "color": "Black",
  "customColor": false,
  "pricePerGram": 0.12
}
```

This route quotes a box, not a mesh, so it is an upper bound — a real model inside that box weighs less. Upload the file at /print for a quote from the model itself.

## Quantity and bulk

| Units | Factor | Discount |
| --- | --- | --- |
| 1–4 | 1.00 | none |
| 5–9 | 0.95 | 5% off |
| 10 or more | 0.90 | 10% off |

*Applied to per-part price x quantity, before the $1.00-per-unit floor.*

> **The cart prices each unit on its own** — Bulk tiers apply where a quantity is quoted as one job: the quote shown on /print, the direct order path behind its Order button, /api/price, and a quantity sent to POST /api/print/orders. A cart line is re-quoted server-side as a single unit and multiplied by its quantity at checkout, so it does not pick up the bulk factor. For ten or more of one part, order it as one job rather than as a cart line, or ask at /contact.

## Multi-colour

A print in colour is priced from a real slice of it in those colours, never from an estimate. There are three ways to get one: a plate you sliced yourself, priced from its own header; a Bambu Studio or OrcaSlicer project, which we slice plate by plate in its own colours; and a model generated in the Studio, which we paint and slice in the colours of its texture. In every case the purge and the filament-change time are already inside the measured grams and hours, so nothing is added on top for them. Charging them twice would be an overcharge.

What colour does change is the rate per gram: +$0.03/g at two colours and +$0.02/g for each colour after (PLA $0.15, $0.17 and $0.19 for two, three and four). The same steps apply to every material that prints in colour (ASA is $0.17/g at two colours), and the quality factor multiplies the whole rate. A colour print spends hours swapping and purging that a one-colour print of the same weight does not: 100 g in one colour is about two hours on the printer, in three colours four to five, so 100 g of PLA is $12.00 in one colour and $17.00 in three. Set by the owner on 21 October 2026.

Colours are counted by what prints. A filament the file assigns but the slicer never feeds is not counted and not charged for. Up to eight colours print, which is two AMS units.

| Colours that print | Added to the order line |
| --- | --- |
| 1 to 4 | Nothing |
| 5 to 8 | $25 second-AMS fee, once per order line whatever the quantity |

*The fee is the second AMS unit being chained on, loaded and mapped by hand for the job. On /print it is its own row in the price, and through the cart it is its own line at Stripe checkout. Print & Ship charges it inside the order's one Stripe line, and your order page counts it in Items either way.*

A colour project is priced at 100% scale and standard quality, at the rate of the base plastic its own filaments name (a plate in PLA-CF is priced as PLA), because that is what its slice measured; those controls are locked on /print while colour is chosen. The surcharge estimate in the pricing code (one filament change per layer per extra colour, 84 mm³ purged per change, 1.3 minutes per change, change hours at $1.50/hour) stays switched off behind a flag, because a real slice sees the changes a plate actually makes. The quote API returns filamentChanges: 0, multiColorGrams: 0 and multiColorHours: 0 for that reason. See /docs/studio/multi-color for how colours are checked and mapped to trays.

## Shipping

| Destination | Flat rate | Free at |
| --- | --- | --- |
| United States, standard | $7.00 | $49.50 subtotal |
| United States, express | $15.00 | Never |
| International | $30.00 | $500.00 subtotal |

Shipping is charged once per order, not per part, and appears as its own line at checkout. One caveat if you are reading the quote API: it returns shipping: 7, or 15 when you send shippingSpeed express, whatever the total, because it prices a part and not a basket. The free-shipping thresholds are applied at cart checkout against the order subtotal. Express is US only.

---

## The other model: reserving a printer by the hour

> **These two price lists must never be mixed** — Ordering a print at /print buys a finished part at an all-in per-gram rate that already contains the machine time. Reserving a printer at /farm buys machine time directly, and the filament on top of it is charged at a separate raw rate. Quote the all-in $0.12/g against reserved hours and you have billed the machine twice. Every figure below belongs to reservations only, and every figure above belongs to prints only.

|  | Ordering a print | Reserving a printer |
| --- | --- | --- |
| Where | /print | /farm |
| What you buy | A finished part, shipped | Time on a machine you drive yourself |
| Machine time | Included in the per-gram rate | $1.50 per hour, or $15.00 per day |
| Filament | Included in the per-gram rate | Charged separately, raw, per gram |
| When you pay | At checkout | Metered on release, settled monthly |
| Card on file | Not required | Required before a reservation starts |

| Reservation line | Rate |
| --- | --- |
| Machine, hourly | $1.50 per hour |
| Machine, daily | $15.00 per day, billed per started day |
| PLA filament | $0.02 per gram |
| PETG filament | $0.025 per gram |
| ABS filament | $0.03 per gram |
| Filament swap | $0.00 |
| Shipping handling, per shipment | $3.00 plus postage |

*Reservation rates only. A material with no entry above is charged at the PLA rate.*

1. You pick a printer that is AVAILABLE and choose hourly (1–24 hours) or daily. A card on file is required — the reservation is refused with 402 and CARD_REQUIRED without one.
2. Nothing is charged at booking. The reservation starts at $0.00 and accrues.
3. Releasing it meters the real elapsed time between reserve and release. Hourly bills elapsed hours x $1.50, rounded to the cent; daily bills each started 24-hour block at $15.00.
4. Filament is billed on what a job actually used, at the raw rate above. A job's machine time is charged from its actual run time whether it finished, failed or was cancelled.
5. The balance settles on the monthly card charge, run on the 1st. A declined card leaves the balance open and emails you rather than cancelling anything.

The public /farm page does not publish these rates, so this page and /docs/farm/reservations are where they live.

- [Cost calculator](https://x3dstudios.com/3d-print-cost-calculator) — Work out a price from a weight, with quantity, colours, print speed and shipping.
- [Materials](https://x3dstudios.com/docs/materials) — What each plastic costs, weighs and survives, and when not to choose it.
- [File formats](https://x3dstudios.com/docs/file-formats) — Why a pre-sliced file is priced from its own header instead of a slice we run.
- [Reservations](https://x3dstudios.com/docs/farm/reservations) — Booking a machine by the hour, and what monthly billing collects.
- [Quote API](https://x3dstudios.com/docs/api/quote) — The full reference for POST /api/price, including every error it returns.

[Price your own model](https://x3dstudios.com/print)

## Frequently asked

**How is the price of a 3D print calculated?**

Billable grams, rounded up to the whole gram, times the material's all-in rate per gram, times the quality factor (1.00 at 0.2mm layers, 1.75 at 0.1mm). There is a $1.00 minimum per part, and shipping is added once per order, as are Priority print and support removal if you choose them.

**Does the per-gram rate include machine time?**

Yes. The rate is all-in: filament and normal machine time in one number. Machine time is billed separately in one case only — a pre-sliced file whose measured hours far exceed what its weight implies, where the excess is charged at $1.50/hour.

**Why is my quote a whole number of grams?**

Billable weight rounds up to the whole gram, like postage. It also keeps the quote in step with Bambu Studio, which displays whole grams — so the weight you were promised a price against is the weight you are charged for.

**Is reserving a printer priced the same way?**

No. A reservation is a different product: $1.50 per hour or $15.00 per day for the machine, plus filament at a separate raw rate per gram. Quoting the all-in per-gram rate against reserved machine time bills the machine twice.
