API
Quickstart: from a key to a price
Three requests gets you a real quote — sliced on a real engine against a real printer profile, not estimated from volume. This page is the short path; the full reference has every field.
Before you start
- A secret key (
sk_test_…orsk_live_…) from your account page. - An STL or 3MF file to quote.
- At least one machine set up on your shop, since a quote is priced against a specific machine's profile.
Test keys run the same code path and the same slicing engines and produce real slices. They just cannot create real orders or move real money — so everything on this page works identically with a test key.
Base URL and auth
# Base URL https://api.3dash.in/v1 # Every request Authorization: Bearer $SK
Secret keys are server-side only. Secret-key routes return no CORS headers at all, so a browser physically cannot call them cross-origin — that is the enforcement, not a warning. If you need to quote from a browser, use your publishable key with the widget, or proxy our API through your own backend.
1Create a model
You do not post the file to us. You ask for somewhere to put it, and get back a signed upload URL.
curl -X POST https://api.3dash.in/v1/models \ -H "Authorization: Bearer $SK" \ -H "Content-Type: application/json" \ -d '{ "filename": "bracket.stl" }'
{
"id": "mdl_8fA2k9",
"upload": {
"method": "PUT",
"url": "https://storage.googleapis.com/…",
"headers": { "Content-Type": "application/octet-stream" },
"expires_at": "2026-08-10T12:05:00Z"
},
"status": "awaiting_upload"
}
2Upload the file
A plain PUT to the URL you were just given, with the headers it specified. This goes straight to storage and does not pass through our API.
curl -X PUT "<upload.url>" \ -H "Content-Type: application/octet-stream" \ --data-binary @bracket.stl
Once the upload lands, the model is inspected and moves to ready. Fetching it back gives you the geometry facts before you commit to a quote:
{
"id": "mdl_8fA2k9", "status": "ready", "filename": "bracket.stl",
"volume_mm3": 14203.7, "bbox_mm": [62.0, 41.5, 18.2],
"triangles": 24880, "is_watertight": true
}
3Create a quote
Slicing takes a moment, so you can either poll or ask the request to wait. ?wait=10 holds the connection for up to ten seconds, which is almost always enough.
curl -X POST "https://api.3dash.in/v1/quotes?wait=10" \ -H "Authorization: Bearer $SK" \ -H "Content-Type: application/json" \ -d '{ "material": "pla", "lines": [{ "model_id": "mdl_8fA2k9", "quantity": 2, "infill": 20, "layer_height_mm": 0.2, "supports": true }] }'
{
"id": "qte_M3xQ1", "status": "completed", "currency": "INR",
"machine_id": "mch_a1", "material": "pla",
"lines": [{
"model_id": "mdl_8fA2k9", "quantity": 2,
"grams": 41.8, "print_seconds": 9420,
"amount": 74000,
"engine": { "name": "prusa-slicer", "version": "2.9.6" },
"flags": [{ "code": "thin_feature", "severity": "warning",
"message": "A section under 1.2 mm may snap during removal." }]
}],
"subtotal": 74000, "delivery": 0, "total": 74000,
"expires_at": "2026-08-17T12:00:00Z"
}
Reading the response
| Field | Unit | Notes |
|---|---|---|
amount, subtotal, total | Integer paise | Never floats. 74000 is ₹740.00. Divide by 100 only at the point you render it. |
grams | Grams | What the spool actually loses, including supports — not model volume converted. |
print_seconds | Integer seconds | The slicer's own estimate for that machine. |
engine | — | Which slicer and version produced the number. Useful when a figure surprises you. |
flags | — | Printability warnings on the geometry, e.g. thin features. Advisory, not a rejection. |
expires_at | Timestamp | Quotes are not open-ended; material prices move. |
A quote never contains a rate. No per-gram figure, no machine hourly cost, no multiplier or minimum — line amounts and totals only. That is deliberate and permanent: the widget lives in a public page and this API may be proxied into one, so pricing inputs stay on the server. A shop reads its own rate card from GET /v1/rate-cards with a secret key, which has no publishable-key access at any tier.
Money, precisely
Every amount in this API is an integer in paise with an explicit currency. There are no rupee floats in either direction. This is not fussiness — rupee-float rounding has already caused a payment refund to fail silently once, and integer paise is the fix.
What else is there
GET /v1/machines— your machines and their build volumes, so you can let a customer choose.GET /v1/materials— what you offer.GET /v1/health— which slicing engines are currently available.POST /v1/orders— Checkout plan only; returns403on the Quote plan.
All of it, with every field and every error code, is in the full API reference. If you would rather not build a front end at all, the drop-in widget does this whole flow for you.