Get started
Quickstart
From zero to your first quote in under five minutes — cURL, Python, TypeScript.
Run your first ARCNM quote in under five minutes: send a STEP file and get back an audited unit price. By the end you'll have run Deep Feature Extraction and Deep Cost Modeling against a real part.
Billed on success. A calculation is billed when it succeeds. Failed runs, 4xx/5xx responses, and idempotent replays don't add usage. A wallet hold is pre-authorised when you run a calculation and released if it fails. New accounts start with a welcome credit worth your first 5 runs — so this quickstart is free. See Pricing.
1. Create an account and an org
Sign up at arcnm.io/signup. The first user in an org is the owner and can mint API keys.
If you already have an account, head to
Settings → API keys.
2. Mint an API key
Settings → API keys → New key. Give it a name, pick the scopes you need, copy the plaintext key. It is shown exactly once.
For this quickstart, grant:
parts:readparts:writeuploads:write
export ARCNM_API_KEY="ak_live_…"
Scopes are enforced per request. A leaked
parts:readkey cannot trigger a billable calculation. See Authentication. Send the key in theX-API-Keyheader (notAuthorization).
3. No SDK required
cURL or any HTTP client is enough — the whole quickstart is plain REST.
The Python and TypeScript tabs below use requests and fetch. (Native
SDKs are on the roadmap; see SDKs.)
curl --version
4. Get a costing environment
A calculation prices a part against a costing environment (your machines + rates). Create one in the dashboard under Environments, or via the API, and copy its id:
export ARCNM_ENV_ID="7c1f…"
5. Upload a STEP and quote it in one call
POST /api/v1/parts/calculations/upload-and-quote is the one-shot
endpoint: it creates a Part + Revision + Dataset from your uploaded
files and enqueues the calculation in a single multipart request.
curl -X POST https://api.arcnm.io/api/v1/parts/calculations/upload-and-quote \
-H "X-API-Key: $ARCNM_API_KEY" \
-F "costing_environment_id=$ARCNM_ENV_ID" \
-F "part_number=BRACKET-001" \
-F "cad_file=@./bracket.step;type=application/step" \
-F "drawing_file=@./bracket.pdf;type=application/pdf" \
-F "lot_size=50" \
-F "annual_volume=500" \
-F "material_ref=1.4301"
import os, requests
API = "https://api.arcnm.io/api/v1"
H = {"X-API-Key": os.environ["ARCNM_API_KEY"]}
with open("bracket.step", "rb") as cad, open("bracket.pdf", "rb") as drw:
r = requests.post(
f"{API}/parts/calculations/upload-and-quote",
headers=H,
data={
"costing_environment_id": os.environ["ARCNM_ENV_ID"],
"part_number": "BRACKET-001",
"lot_size": 50,
"annual_volume": 500,
"material_ref": "1.4301",
},
files={"cad_file": cad, "drawing_file": drw},
)
r.raise_for_status()
calc = r.json()
print(calc["id"], calc["status"]) # e.g. ('9d…', 'queued')
import { readFile } from "node:fs/promises"
const API = "https://api.arcnm.io/api/v1"
const H = { "X-API-Key": process.env.ARCNM_API_KEY! }
const form = new FormData()
form.set("costing_environment_id", process.env.ARCNM_ENV_ID!)
form.set("part_number", "BRACKET-001")
form.set("lot_size", "50")
form.set("annual_volume", "500")
form.set("material_ref", "1.4301")
form.set("cad_file", new Blob([await readFile("./bracket.step")]), "bracket.step")
form.set("drawing_file", new Blob([await readFile("./bracket.pdf")]), "bracket.pdf")
const res = await fetch(`${API}/parts/calculations/upload-and-quote`, {
method: "POST", headers: H, body: form,
})
const calc = await res.json()
console.log(calc.id, calc.status)
Response (202 Accepted):
{
"id": "9d8f3b62-…",
"status": "queued"
}
6. Poll for the result
Calculations finish in seconds for typical milled parts. Poll
GET /api/v1/parts/calculations/{id} until status is terminal.
curl https://api.arcnm.io/api/v1/parts/calculations/9d8f3b62-… \
-H "X-API-Key: $ARCNM_API_KEY"
import time
while True:
calc = requests.get(f"{API}/parts/calculations/{calc['id']}", headers=H).json()
if calc["status"] in ("succeeded", "failed", "cancelled", "timed_out"):
break
time.sleep(2)
print(calc["status"], calc["unit_cost"], calc["currency"])
let result = calc
while (!["succeeded", "failed", "cancelled", "timed_out"].includes(result.status)) {
await new Promise((r) => setTimeout(r, 2000))
result = await (await fetch(`${API}/parts/calculations/${calc.id}`, { headers: H })).json()
}
console.log(result.status, result.unit_cost, result.currency)
A successful response carries the unit cost, totals, cycle times, and an
analytics audit blob:
{
"id": "9d8f3b62-…",
"status": "succeeded",
"engine": "arcanum",
"currency": "EUR",
"unit_cost": 12.84,
"total_cost": 642.0,
"setup_cost": 52.5,
"unit_time_s": 184.0,
"total_time_s": 9200.0,
"analytics": { "...": "audit blob — see Concepts → Audit" },
"finished_at": "2026-05-28T14:23:32Z"
}
That's it. You've priced a part end-to-end. See the Calculations reference for the full field list.
Next steps
- Audit & provenance — how a quote traces back to its inputs.
- Adaptive Calibration — tune ARCNM to your tenant's machines, rates, and historical data.
- Webhooks — subscribe to wallet and account events.
- MCP — let Claude or Cursor quote parts inside the agent loop.
- Errors — what to catch and how to retry safely.