---
title: Quickstart
description: From zero to your first quote in under five minutes — cURL, Python, TypeScript.
---

# Quickstart

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](./pricing.md).

---

## 1. Create an account and an org

Sign up at [arcnm.io/signup](https://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`](https://app.arcnm.io/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:read`
- `parts:write`
- `uploads:write`

```bash
export ARCNM_API_KEY="ak_live_…"
```

> **Scopes are enforced per request.** A leaked `parts:read` key cannot
> trigger a billable calculation. See [Authentication](./authentication.md#scopes).
> Send the key in the `X-API-Key` header (not `Authorization`).

## 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](./sdks.md).)

```bash
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:

```bash
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.

<CodeTabs>

```bash title="cURL"
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"
```

```python title="Python"
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')
```

```typescript title="TypeScript"
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)
```

</CodeTabs>

Response (`202 Accepted`):

```json
{
  "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.

<CodeTabs>

```bash title="cURL"
curl https://api.arcnm.io/api/v1/parts/calculations/9d8f3b62-… \
  -H "X-API-Key: $ARCNM_API_KEY"
```

```python title="Python"
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"])
```

```typescript title="TypeScript"
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)
```

</CodeTabs>

A successful response carries the unit cost, totals, cycle times, and an
`analytics` audit blob:

```json
{
  "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](./api/calculations.md) for the full field list.

---

## Next steps

- **[Audit & provenance](./concepts/audit-provenance.md)** — how a quote
  traces back to its inputs.
- **[Adaptive Calibration](./concepts/calibration-environments.md)** —
  tune ARCNM to your tenant's machines, rates, and historical data.
- **[Webhooks](./webhooks.md)** — subscribe to wallet and account events.
- **[MCP](./mcp.md)** — let Claude or Cursor quote parts inside the
  agent loop.
- **[Errors](./errors.md)** — what to catch and how to retry safely.
