---
title: Materials & overrides
description: Resolve any material reference to a canonical grade, then override the catalogue per tenant so cost lands on the metal you actually buy.
---

# Materials and overrides

Material is one of the largest line items in a machined part, so every
quote has to land on the **grade you actually buy** — not a generic
"steel". ARCNM ships a canonical catalogue of material grades and a
resolver that maps your references — Werkstoffnummer, AISI/SAE code,
trade name, or your own SKU — onto it.

There are two layers:

- **The platform catalogue** — a read-only set of canonical grades
  (1.4301, AISI 304, Ti-6Al-4V, …), each with a density, ISO machining
  group, and a stable URN. Shared by every tenant.
- **Your overrides** — per-tenant rows that extend the catalogue: map an
  internal code or trade name onto a canonical grade, or define a fully
  org-private material.

---

## Discover a grade

Resolve the material you mean *before* you quote. Three read paths, all
on the `parts:read` scope.

### Search the catalogue

`GET /api/v1/parts/materials/grades` searches across primary code,
display code, name, URN, **and** every alias — so `AISI 304`, `SUS304`,
and `S30400` all return **1.4301**. Filter by `category` or `iso_group`,
and page with `limit` / `offset`.

```bash
curl "https://api.arcnm.io/api/v1/parts/materials/grades?q=AISI%20304&limit=5" \
  -H "X-API-Key: $ARCNM_API_KEY"
# → { "count": 1, "data": [ { "id": "…", "urn": "urn:material:din:1.4301",
#     "primary_code": "1.4301", "name": "X5CrNi18-10", "iso_machining_group": "P", … } ] }
```

### Resolve a single reference

When you have one string from a drawing or an ERP export, `POST
/api/v1/parts/materials/lookup` returns the best canonical match (or
`404` if nothing matches). Resolve a whole drawing's worth of candidates
in one round-trip with `POST .../lookup/batch` (up to 100; misses come
back in-band so you can correlate by position).

```bash
curl -X POST https://api.arcnm.io/api/v1/parts/materials/lookup \
  -H "X-API-Key: $ARCNM_API_KEY" -H "Content-Type: application/json" \
  -d '{ "query": "1.4301" }'
```

### Fetch by id or URN

`GET .../grades/{grade_id}` and `GET .../grades/by-urn/{urn}` return the
full grade with its aliases. `GET .../materials/standards` lists the
standards bodies (DIN, AISI, …) the catalogue is keyed against.

---

## Use a material in a calculation

Hand ARCNM either reference when you quote — the typed
`material_grade_id` (from a lookup) or a free-form `material_ref`:

```json
{
  "part_revision_id": "1f…",
  "costing_environment_id": "env_2a…",
  "material_ref": "1.4301"
}
```

`material_grade_id` wins if both are supplied. A reference that can't be
resolved comes back as `material_not_resolved` (`422`) — resolve it with
`/lookup` first, or add an override.

---

## Override the catalogue

When your shop floor calls a grade by an internal code, or you buy a
material the platform catalogue doesn't carry, create an **override**
(`parts:write`):

- **Map an internal code → a canonical grade.** Your `INOX-A2` resolves
  to 1.4301 for everyone on the org.
- **Define an org-private material.** Carry your own URN + properties for
  a grade ARCNM doesn't ship.

```json
POST /api/v1/parts/materials/overrides
{
  "material_grade_id": "…",            // extend a canonical grade …
  "internal_code": "INOX-A2",
  "trade_name": "Acme Stainless A2"
}
```

An override must either reference a canonical `material_grade_id` **or**
carry its own `urn` for a fully private material. List, patch, and delete
them under `.../materials/overrides`. Once created, your codes resolve
through `/lookup` and on every `material_ref` you pass to a calculation.

---

## See also

- [API → Materials](../api/materials.md) — every field, filter, and override route.
- [Concepts → Cost & lot-size](./cost-and-lot-size.md) — where material mass lands in the price.
- [Recipe → ERP integration](../recipes/erp-integration.md) — feed your ERP's material codes in.
