Pricing model
How a print quote is computed at X3D: the all-in per-gram rate, the quality multiplier, gram rounding, bulk tiers and shipping, with a worked example.
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#
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 + shippingEverything 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.
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.13 | 1.21 g/cm³ |
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.
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 and the filament volume it reports is converted to grams with the material's density. 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 upload (.gcode, .3mf, .gcode.3mf) is always measured — the grams and hours come out of the file's own header, and they already contain every purge, support and brim.
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.
- 1Start 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³.
text60 x 40 x 30 / 1000 = 72 cm3 - 2Apply walls and infill
30% of the volume is solid wall; the remaining 70% is filled to the requested infill.
text72 x (0.30 + 0.70 x 0.20) = 31.68 cm3 - 3Convert to weight
Multiply by the density of PLA, 1.26 g/cm³.
text31.68 x 1.26 = 39.92 g - 4Round up
Billable weight is a whole number of grams.
textceil(39.92) = 40 g - 5Apply 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.
text40 x 0.12 x 1.00 = $4.80 per part - 6Multiply by quantity, then add shipping
One unit gets no bulk discount, and US shipping is $7.00 flat below $50.
text4.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.
/api/priceNo authQuote a bounding box. No authentication, no rate limit, no order is created.
bboxMmobjectrequired- 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.
materialstringoptionaldefaultpla- Anything else is rejected with unknown material: <value>.
plapetgabsasatpu qualitystringoptionaldefaultstandard- Anything else is rejected with unknown quality: <value>.
standardpremium quantitynumberoptionaldefault1- Rounded, and floored at 1. Bulk tiers are applied from this number.
colorstringoptional- 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.
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"
}'{
"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 |
Multi-colour#
Nothing is added for colour. A model we slice for you is printed as a single-filament plate — multi-colour is not orderable yet — so a model that looks multi-coloured on screen is quoted and charged at exactly the single-colour price. The quote returns filamentChanges: 0, multiColorGrams: 0 and multiColorHours: 0 on every print for that reason.
The surcharge model does exist in the pricing code, switched off behind a flag, ready for the day a four-colour plate can actually be printed: one filament change per layer per extra colour, 84 mm³ purged per change (the flush volume in the Bambu H2S profile), 1.3 minutes per change, purge grams added before rounding and change hours at $1.50/hour. None of it reaches a quote today.
A file you sliced yourself is the one way to buy a multi-colour print now, and it is priced from its own header: the purge and the tool-change hours are already inside its measured grams and hours, so nothing is added on top. Charging it twice would be an overcharge. See /docs/studio/multi-color for how colours are mapped to trays.
Shipping#
| Destination | Flat rate | Free at |
|---|---|---|
| United States | $7.00 | $50.00 subtotal |
| 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 always returns shipping: 7, because it prices a part and not a basket. The free-shipping thresholds are applied at checkout against the order subtotal.
The other model: reserving a printer by the hour#
| Ordering a print | Reserving a printer | |
|---|---|---|
| Where | /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 |
- 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.
- Nothing is charged at booking. The reservation starts at $0.00 and accrues.
- 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.
- 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.
- 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.
What each plastic costs, weighs and survives, and when not to choose it.
Why a pre-sliced file is priced from its own header instead of a slice we run.
Booking a machine by the hour, and what monthly billing collects.
The full reference for POST /api/price, including every error it returns.