---
title: Materials
description: The Materials API looks up material grades and manages per-tenant overrides.
---

# Materials

The Materials API looks up material grades and manages per-tenant overrides: search grades, resolve one by URN, and create, update, or delete cost overrides.

> **Auto-generated** from the public OpenAPI spec — this page never
> drifts from the running API. Base URL `https://api.arcnm.io`. Authenticate with
> the `X-API-Key` header (see [Authentication](../authentication.md)).

## List Grades

`GET /api/v1/parts/materials/grades`

List canonical grades.

``q`` searches across ``primary_code``, ``display_code``, ``name``,
``urn`` AND every alias's ``code``/``display_code``. A user typing
"AISI 304", "SUS304" or "S30400" therefore finds 1.4301 from this
single endpoint — no need to fall back to POST ``/lookup``.

Returns the **total** matching row count (not page size) so the
frontend can paginate properly.

> **Paginated.** Pass `limit` and `offset` to page through results.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `category` | query | `carbon_steel` \| `alloy_steel` \| `stainless_steel` \| `tool_steel` \| `cast_iron` \| `aluminium` \| `copper_alloy` \| `nickel_alloy` \| `titanium_alloy` \| `magnesium_alloy` \| `zinc_alloy` \| `thermoplastic` \| `thermoset` \| `elastomer` \| `composite` \| `other` | no | Filter by material category (e.g. stainless_steel, aluminium). |
| `iso_group` | query | `P` \| `M` \| `K` \| `N` \| `S` \| `H` | no | Filter by ISO 513 machining group (P, M, K, N, S, H). |
| `q` | query | string | no | Free-text search across grade codes, names, URNs, and aliases. |
| `limit` | query | integer | no | Maximum number of results to return. |
| `offset` | query | integer | no | Number of results to skip before the returned page. |

**Request**

<CodeTabs>

```bash title="cURL"
curl -X GET https://api.arcnm.io/api/v1/parts/materials/grades \
  -H "X-API-Key: $ARCNM_API_KEY"
```

```python title="Python"
import requests

resp = requests.get(
    "https://api.arcnm.io/api/v1/parts/materials/grades",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
resp.raise_for_status()
print(resp.json())
```

```typescript title="TypeScript"
const resp = await fetch("https://api.arcnm.io/api/v1/parts/materials/grades", {
  method: "GET",
  headers: {
    "X-API-Key": process.env.ARCNM_API_KEY!,
  },
})
const data = await resp.json()
```

</CodeTabs>

**Responses**

| Status | Description |
| --- | --- |
| `200` | Successful Response |
| `422` | Validation Error |

**Errors**

Standard error responses — see the [Errors catalog](../errors.md) for the full envelope, `request_id`, and retry-safety table.

| Status | Code | When |
| --- | --- | --- |
| `401` | `invalid_api_key` | Missing, malformed, or revoked API key. |
| `403` | `insufficient_scope` | The key is valid but lacks a scope this endpoint requires. |
| `429` | `rate_limited` | Per-key or per-org rate limit exceeded — back off with jitter and retry. |


**Response body** `200`

| Field | Type | Description |
| --- | --- | --- |
| `count` | integer | Total number of grades matching the query (not the page size). |
| `data` | MaterialGradePublic[] | The material grades on this page. |

**Example response**

```json
{
  "count": 0,
  "data": [
    {
      "aliases": [
        {}
      ],
      "attributes": {},
      "category": "carbon_steel",
      "created_at": "2026-06-01T12:00:00Z",
      "density_kg_per_m3": 0,
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "is_active": true,
      "iso_machining_group": "P",
      "name": "string",
      "primary_code": "string",
      "primary_standard_code": "en10027-1",
      "primary_standard_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "successor_grade_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "updated_at": "2026-06-01T12:00:00Z",
      "urn": "string"
    }
  ]
}
```

## Get Grade

`GET /api/v1/parts/materials/grades/{grade_id}`

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `grade_id` | path | string | yes | Identifier of the grade. |

**Request**

<CodeTabs>

```bash title="cURL"
curl -X GET https://api.arcnm.io/api/v1/parts/materials/grades/{grade_id} \
  -H "X-API-Key: $ARCNM_API_KEY"
```

```python title="Python"
import requests

resp = requests.get(
    "https://api.arcnm.io/api/v1/parts/materials/grades/{grade_id}",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
resp.raise_for_status()
print(resp.json())
```

```typescript title="TypeScript"
const resp = await fetch("https://api.arcnm.io/api/v1/parts/materials/grades/{grade_id}", {
  method: "GET",
  headers: {
    "X-API-Key": process.env.ARCNM_API_KEY!,
  },
})
const data = await resp.json()
```

</CodeTabs>

**Responses**

| Status | Description |
| --- | --- |
| `200` | Successful Response |
| `422` | Validation Error |

**Errors**

Standard error responses — see the [Errors catalog](../errors.md) for the full envelope, `request_id`, and retry-safety table.

| Status | Code | When |
| --- | --- | --- |
| `401` | `invalid_api_key` | Missing, malformed, or revoked API key. |
| `403` | `insufficient_scope` | The key is valid but lacks a scope this endpoint requires. |
| `404` | `not_found` | A referenced resource doesn't exist or isn't visible to your organisation. |
| `429` | `rate_limited` | Per-key or per-org rate limit exceeded — back off with jitter and retry. |


**Response body** `200`

| Field | Type | Description |
| --- | --- | --- |
| `aliases` | MaterialGradeAliasPublic[] | Cross-references mapping this grade's code across other standards and trade names. |
| `attributes` | object | Free-form key/value metadata for extra mechanical and physical properties. |
| `category` | `carbon_steel` \| `alloy_steel` \| `stainless_steel` \| `tool_steel` \| `cast_iron` \| `aluminium` \| `copper_alloy` \| `nickel_alloy` \| `titanium_alloy` \| `magnesium_alloy` \| `zinc_alloy` \| `thermoplastic` \| `thermoset` \| `elastomer` \| `composite` \| `other` | Broad material family the grade belongs to (e.g. steel, aluminium, polymer). |
| `created_at` | string | Timestamp when the grade record was created. |
| `density_kg_per_m3` | number | Material density in kilograms per cubic metre. |
| `id` | string | Unique identifier of the material grade. |
| `is_active` | boolean | Whether the grade is currently active and selectable; false when retired. |
| `iso_machining_group` | `P` \| `M` \| `K` \| `N` \| `S` \| `H` | ISO 513 machining group (P/M/K/N/S/H) used to gauge machinability. |
| `name` | string | Human-readable name of the material grade. |
| `primary_code` | string | Standards-compliant cased display code; the same value as `display_code`. |
| `primary_standard_code` | `en10027-1` \| `en10027-2` \| `en10025` \| `en10083` \| `en10084` \| `en10088` \| `en-iso-4957` \| `en573-1` \| `en573-2` \| `en1412` \| `en1560` \| `en1561` \| `en1563` \| `iso1043-1` \| `iso1043-2` \| `iso18064` \| `uns` \| `aisi-sae` \| `jis` \| `astm` \| `eclass` \| `unspsc` | URN-safe code of the primary standard (``en10027-2``, ``iso1043-1``, …). Hydrated by the routes layer so frontends can render a badge without a second round-trip. |
| `primary_standard_id` | string | Identifier of the standard that defines this grade's primary code. |
| `successor_grade_id` | string | Identifier of the grade that supersedes this one; null when still current. |
| `updated_at` | string | Timestamp when the grade record was last updated. |
| `urn` | string | Canonical URN that uniquely and stably identifies this grade across systems. |

**Example response**

```json
{
  "aliases": [
    {
      "code": "string",
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "is_canonical": false,
      "is_preferred_display": true,
      "material_grade_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "standard_code": "en10027-1",
      "standard_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
    }
  ],
  "attributes": {},
  "category": "carbon_steel",
  "created_at": "2026-06-01T12:00:00Z",
  "density_kg_per_m3": 0,
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "is_active": true,
  "iso_machining_group": "P",
  "name": "string",
  "primary_code": "string",
  "primary_standard_code": "en10027-1",
  "primary_standard_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "successor_grade_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "updated_at": "2026-06-01T12:00:00Z",
  "urn": "string"
}
```

## Get Grade By Urn

`GET /api/v1/parts/materials/grades/by-urn/{urn}`

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `urn` | path | string | yes | Material grade URN to resolve (e.g. urn:material:cen:1.4301). |

**Request**

<CodeTabs>

```bash title="cURL"
curl -X GET https://api.arcnm.io/api/v1/parts/materials/grades/by-urn/{urn} \
  -H "X-API-Key: $ARCNM_API_KEY"
```

```python title="Python"
import requests

resp = requests.get(
    "https://api.arcnm.io/api/v1/parts/materials/grades/by-urn/{urn}",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
resp.raise_for_status()
print(resp.json())
```

```typescript title="TypeScript"
const resp = await fetch("https://api.arcnm.io/api/v1/parts/materials/grades/by-urn/{urn}", {
  method: "GET",
  headers: {
    "X-API-Key": process.env.ARCNM_API_KEY!,
  },
})
const data = await resp.json()
```

</CodeTabs>

**Responses**

| Status | Description |
| --- | --- |
| `200` | Successful Response |
| `422` | Validation Error |

**Errors**

Standard error responses — see the [Errors catalog](../errors.md) for the full envelope, `request_id`, and retry-safety table.

| Status | Code | When |
| --- | --- | --- |
| `401` | `invalid_api_key` | Missing, malformed, or revoked API key. |
| `403` | `insufficient_scope` | The key is valid but lacks a scope this endpoint requires. |
| `404` | `not_found` | A referenced resource doesn't exist or isn't visible to your organisation. |
| `429` | `rate_limited` | Per-key or per-org rate limit exceeded — back off with jitter and retry. |


**Response body** `200`

| Field | Type | Description |
| --- | --- | --- |
| `aliases` | MaterialGradeAliasPublic[] | Cross-references mapping this grade's code across other standards and trade names. |
| `attributes` | object | Free-form key/value metadata for extra mechanical and physical properties. |
| `category` | `carbon_steel` \| `alloy_steel` \| `stainless_steel` \| `tool_steel` \| `cast_iron` \| `aluminium` \| `copper_alloy` \| `nickel_alloy` \| `titanium_alloy` \| `magnesium_alloy` \| `zinc_alloy` \| `thermoplastic` \| `thermoset` \| `elastomer` \| `composite` \| `other` | Broad material family the grade belongs to (e.g. steel, aluminium, polymer). |
| `created_at` | string | Timestamp when the grade record was created. |
| `density_kg_per_m3` | number | Material density in kilograms per cubic metre. |
| `id` | string | Unique identifier of the material grade. |
| `is_active` | boolean | Whether the grade is currently active and selectable; false when retired. |
| `iso_machining_group` | `P` \| `M` \| `K` \| `N` \| `S` \| `H` | ISO 513 machining group (P/M/K/N/S/H) used to gauge machinability. |
| `name` | string | Human-readable name of the material grade. |
| `primary_code` | string | Standards-compliant cased display code; the same value as `display_code`. |
| `primary_standard_code` | `en10027-1` \| `en10027-2` \| `en10025` \| `en10083` \| `en10084` \| `en10088` \| `en-iso-4957` \| `en573-1` \| `en573-2` \| `en1412` \| `en1560` \| `en1561` \| `en1563` \| `iso1043-1` \| `iso1043-2` \| `iso18064` \| `uns` \| `aisi-sae` \| `jis` \| `astm` \| `eclass` \| `unspsc` | URN-safe code of the primary standard (``en10027-2``, ``iso1043-1``, …). Hydrated by the routes layer so frontends can render a badge without a second round-trip. |
| `primary_standard_id` | string | Identifier of the standard that defines this grade's primary code. |
| `successor_grade_id` | string | Identifier of the grade that supersedes this one; null when still current. |
| `updated_at` | string | Timestamp when the grade record was last updated. |
| `urn` | string | Canonical URN that uniquely and stably identifies this grade across systems. |

**Example response**

```json
{
  "aliases": [
    {
      "code": "string",
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "is_canonical": false,
      "is_preferred_display": true,
      "material_grade_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "standard_code": "en10027-1",
      "standard_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
    }
  ],
  "attributes": {},
  "category": "carbon_steel",
  "created_at": "2026-06-01T12:00:00Z",
  "density_kg_per_m3": 0,
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "is_active": true,
  "iso_machining_group": "P",
  "name": "string",
  "primary_code": "string",
  "primary_standard_code": "en10027-1",
  "primary_standard_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "successor_grade_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "updated_at": "2026-06-01T12:00:00Z",
  "urn": "string"
}
```

## Lookup

`POST /api/v1/parts/materials/lookup`

**Request body** (`application/json`)

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `query` | string | yes | URN, EN/UNS/AISI/JIS code, trade name, or org internal code. |
| `standard` | `en10027-1` \| `en10027-2` \| `en10025` \| `en10083` \| `en10084` \| `en10088` \| `en-iso-4957` \| `en573-1` \| `en573-2` \| `en1412` \| `en1560` \| `en1561` \| `en1563` \| `iso1043-1` \| `iso1043-2` \| `iso18064` \| `uns` \| `aisi-sae` \| `jis` \| `astm` \| `eclass` \| `unspsc` | no | Optional hint — restrict alias search to this standard. |

**Request**

<CodeTabs>

```bash title="cURL"
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": "string"
  }'
```

```python title="Python"
import requests

resp = requests.post(
    "https://api.arcnm.io/api/v1/parts/materials/lookup",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "query": "string"
    },
)
resp.raise_for_status()
print(resp.json())
```

```typescript title="TypeScript"
const resp = await fetch("https://api.arcnm.io/api/v1/parts/materials/lookup", {
  method: "POST",
  headers: {
    "X-API-Key": process.env.ARCNM_API_KEY!,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "query": "string"
  }),
})
const data = await resp.json()
```

</CodeTabs>

**Responses**

| Status | Description |
| --- | --- |
| `200` | Successful Response |
| `422` | Validation Error |

**Errors**

Standard error responses — see the [Errors catalog](../errors.md) for the full envelope, `request_id`, and retry-safety table.

| Status | Code | When |
| --- | --- | --- |
| `401` | `invalid_api_key` | Missing, malformed, or revoked API key. |
| `403` | `insufficient_scope` | The key is valid but lacks a scope this endpoint requires. |
| `409` | `conflict` | A conflicting change, or an `Idempotency-Key` reused with a different body. |
| `429` | `rate_limited` | Per-key or per-org rate limit exceeded — back off with jitter and retry. |


**Response body** `200`

| Field | Type | Description |
| --- | --- | --- |
| `grade` | MaterialGradePublic | The canonical material grade the query resolved to. |
| `matched_via` | `urn` \| `legacy_urn` \| `primary_code` \| `alias` \| `org_override` \| `org_private` | Path the resolver used: ``urn`` | ``legacy_urn`` | ``primary_code`` | ``alias`` | ``org_override`` | ``org_private``. |
| `standard_used` | `en10027-1` \| `en10027-2` \| `en10025` \| `en10083` \| `en10084` \| `en10088` \| `en-iso-4957` \| `en573-1` \| `en573-2` \| `en1412` \| `en1560` \| `en1561` \| `en1563` \| `iso1043-1` \| `iso1043-2` \| `iso18064` \| `uns` \| `aisi-sae` \| `jis` \| `astm` \| `eclass` \| `unspsc` | Material standard the match resolved against; null if not standard-specific. |

**Example response**

```json
{
  "grade": {
    "aliases": [
      {
        "code": "string",
        "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "is_canonical": false,
        "is_preferred_display": true,
        "material_grade_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "standard_code": "en10027-1",
        "standard_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
      }
    ],
    "attributes": {},
    "category": "carbon_steel",
    "created_at": "2026-06-01T12:00:00Z",
    "density_kg_per_m3": 0,
    "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "is_active": true,
    "iso_machining_group": "P",
    "name": "string",
    "primary_code": "string",
    "primary_standard_code": "en10027-1",
    "primary_standard_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "successor_grade_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "updated_at": "2026-06-01T12:00:00Z",
    "urn": "string"
  },
  "matched_via": "urn",
  "standard_used": "en10027-1"
}
```

## Lookup Batch

`POST /api/v1/parts/materials/lookup/batch`

Bulk-resolve up to 100 queries in one round-trip.

Drawing extractors emit N candidate strings per part; the worker
and the frontend typeahead both call this endpoint instead of N
individual ``/lookup`` requests. Misses are returned in-band with
``result=null`` so callers can correlate hits/misses by position.

**Request body** (`application/json`)

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `queries` | string[] | yes | Material query strings to resolve in one round-trip (1–100). |
| `standard` | `en10027-1` \| `en10027-2` \| `en10025` \| `en10083` \| `en10084` \| `en10088` \| `en-iso-4957` \| `en573-1` \| `en573-2` \| `en1412` \| `en1560` \| `en1561` \| `en1563` \| `iso1043-1` \| `iso1043-2` \| `iso18064` \| `uns` \| `aisi-sae` \| `jis` \| `astm` \| `eclass` \| `unspsc` | no | Optional hint applied to every query in the batch. |

**Request**

<CodeTabs>

```bash title="cURL"
curl -X POST https://api.arcnm.io/api/v1/parts/materials/lookup/batch \
  -H "X-API-Key: $ARCNM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "queries": [
      "string"
    ]
  }'
```

```python title="Python"
import requests

resp = requests.post(
    "https://api.arcnm.io/api/v1/parts/materials/lookup/batch",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "queries": [
            "string"
        ]
    },
)
resp.raise_for_status()
print(resp.json())
```

```typescript title="TypeScript"
const resp = await fetch("https://api.arcnm.io/api/v1/parts/materials/lookup/batch", {
  method: "POST",
  headers: {
    "X-API-Key": process.env.ARCNM_API_KEY!,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "queries": [
      "string"
    ]
  }),
})
const data = await resp.json()
```

</CodeTabs>

**Responses**

| Status | Description |
| --- | --- |
| `200` | Successful Response |
| `422` | Validation Error |

**Errors**

Standard error responses — see the [Errors catalog](../errors.md) for the full envelope, `request_id`, and retry-safety table.

| Status | Code | When |
| --- | --- | --- |
| `401` | `invalid_api_key` | Missing, malformed, or revoked API key. |
| `403` | `insufficient_scope` | The key is valid but lacks a scope this endpoint requires. |
| `409` | `conflict` | A conflicting change, or an `Idempotency-Key` reused with a different body. |
| `429` | `rate_limited` | Per-key or per-org rate limit exceeded — back off with jitter and retry. |


**Response body** `200`

| Field | Type | Description |
| --- | --- | --- |
| `entries` | MaterialLookupBatchEntry[] | One result slot per query, in the order the queries were supplied. |
| `matched_count` | integer | Number of queries in the batch that resolved to a grade. |
| `miss_count` | integer | Number of queries in the batch that did not resolve. |

**Example response**

```json
{
  "entries": [
    {
      "query": "string",
      "result": {
        "grade": {},
        "matched_via": "urn",
        "standard_used": "en10027-1"
      }
    }
  ],
  "matched_count": 0,
  "miss_count": 0
}
```

## List Overrides

`GET /api/v1/parts/materials/overrides`

**Request**

<CodeTabs>

```bash title="cURL"
curl -X GET https://api.arcnm.io/api/v1/parts/materials/overrides \
  -H "X-API-Key: $ARCNM_API_KEY"
```

```python title="Python"
import requests

resp = requests.get(
    "https://api.arcnm.io/api/v1/parts/materials/overrides",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
resp.raise_for_status()
print(resp.json())
```

```typescript title="TypeScript"
const resp = await fetch("https://api.arcnm.io/api/v1/parts/materials/overrides", {
  method: "GET",
  headers: {
    "X-API-Key": process.env.ARCNM_API_KEY!,
  },
})
const data = await resp.json()
```

</CodeTabs>

**Responses**

| Status | Description |
| --- | --- |
| `200` | Successful Response |
| `422` | Validation Error |

**Errors**

Standard error responses — see the [Errors catalog](../errors.md) for the full envelope, `request_id`, and retry-safety table.

| Status | Code | When |
| --- | --- | --- |
| `401` | `invalid_api_key` | Missing, malformed, or revoked API key. |
| `403` | `insufficient_scope` | The key is valid but lacks a scope this endpoint requires. |
| `429` | `rate_limited` | Per-key or per-org rate limit exceeded — back off with jitter and retry. |


## Create Override

`POST /api/v1/parts/materials/overrides`

**Request body** (`application/json`)

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `attributes` | object | no | Free-form key/value metadata attached to this material by the organization. |
| `internal_code` | string | no | Org-internal SKU / part code for this material. |
| `material_grade_id` | string | no | Canonical grade this override extends. NULL → fully org-private material not in the global catalogue (requires ``urn`` populated). |
| `notes` | string | no | Free-text notes attached to this material by the organization. |
| `trade_name` | string | no | Vendor trade name (e.g. 'Inconel 718'). |
| `urn` | string | no | Canonical or org-private URN (urn:arc:mat:…:…). |

**Request**

<CodeTabs>

```bash title="cURL"
curl -X POST https://api.arcnm.io/api/v1/parts/materials/overrides \
  -H "X-API-Key: $ARCNM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "attributes": {},
    "internal_code": "string",
    "material_grade_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "notes": "string",
    "trade_name": "string",
    "urn": "string"
  }'
```

```python title="Python"
import requests

resp = requests.post(
    "https://api.arcnm.io/api/v1/parts/materials/overrides",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "attributes": {},
        "internal_code": "string",
        "material_grade_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "notes": "string",
        "trade_name": "string",
        "urn": "string"
    },
)
resp.raise_for_status()
print(resp.json())
```

```typescript title="TypeScript"
const resp = await fetch("https://api.arcnm.io/api/v1/parts/materials/overrides", {
  method: "POST",
  headers: {
    "X-API-Key": process.env.ARCNM_API_KEY!,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "attributes": {},
    "internal_code": "string",
    "material_grade_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "notes": "string",
    "trade_name": "string",
    "urn": "string"
  }),
})
const data = await resp.json()
```

</CodeTabs>

**Responses**

| Status | Description |
| --- | --- |
| `201` | Successful Response |
| `422` | Validation Error |

**Errors**

Standard error responses — see the [Errors catalog](../errors.md) for the full envelope, `request_id`, and retry-safety table.

| Status | Code | When |
| --- | --- | --- |
| `401` | `invalid_api_key` | Missing, malformed, or revoked API key. |
| `403` | `insufficient_scope` | The key is valid but lacks a scope this endpoint requires. |
| `409` | `conflict` | A conflicting change, or an `Idempotency-Key` reused with a different body. |
| `429` | `rate_limited` | Per-key or per-org rate limit exceeded — back off with jitter and retry. |


**Response body** `201`

| Field | Type | Description |
| --- | --- | --- |
| `attributes` | object | Free-form key/value metadata attached to this material by the organization. |
| `created_at` | string | Timestamp when the override was created. |
| `id` | string | Unique identifier of the override. |
| `internal_code` | string | Org-internal SKU / part code for this material. |
| `material_grade_id` | string | Identifier of the canonical grade this override extends; null when fully org-private. |
| `notes` | string | Free-text notes attached to this material by the organization. |
| `org_id` | string | Identifier of the organization that owns this override. |
| `trade_name` | string | Vendor trade name (e.g. 'Inconel 718'). |
| `updated_at` | string | Timestamp when the override was last updated. |
| `urn` | string | Canonical or org-private URN identifying the material. |

**Example response**

```json
{
  "attributes": {},
  "created_at": "2026-06-01T12:00:00Z",
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "internal_code": "string",
  "material_grade_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "notes": "string",
  "org_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "trade_name": "string",
  "updated_at": "2026-06-01T12:00:00Z",
  "urn": "string"
}
```

## Delete Override

`DELETE /api/v1/parts/materials/overrides/{override_id}`

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `override_id` | path | string | yes | Identifier of the override. |

**Request**

<CodeTabs>

```bash title="cURL"
curl -X DELETE https://api.arcnm.io/api/v1/parts/materials/overrides/{override_id} \
  -H "X-API-Key: $ARCNM_API_KEY"
```

```python title="Python"
import requests

resp = requests.delete(
    "https://api.arcnm.io/api/v1/parts/materials/overrides/{override_id}",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
resp.raise_for_status()
print(resp.json())
```

```typescript title="TypeScript"
const resp = await fetch("https://api.arcnm.io/api/v1/parts/materials/overrides/{override_id}", {
  method: "DELETE",
  headers: {
    "X-API-Key": process.env.ARCNM_API_KEY!,
  },
})
const data = await resp.json()
```

</CodeTabs>

**Responses**

| Status | Description |
| --- | --- |
| `200` | Successful Response |
| `422` | Validation Error |

**Errors**

Standard error responses — see the [Errors catalog](../errors.md) for the full envelope, `request_id`, and retry-safety table.

| Status | Code | When |
| --- | --- | --- |
| `401` | `invalid_api_key` | Missing, malformed, or revoked API key. |
| `403` | `insufficient_scope` | The key is valid but lacks a scope this endpoint requires. |
| `404` | `not_found` | A referenced resource doesn't exist or isn't visible to your organisation. |
| `409` | `conflict` | A conflicting change, or an `Idempotency-Key` reused with a different body. |
| `429` | `rate_limited` | Per-key or per-org rate limit exceeded — back off with jitter and retry. |


**Response body** `200`

| Field | Type | Description |
| --- | --- | --- |
| `message` | string | Human-readable confirmation that the resource was deleted. |

**Example response**

```json
{
  "message": "string"
}
```

## Update Override

`PATCH /api/v1/parts/materials/overrides/{override_id}`

Partial update. Only fields explicitly present in the body are
applied — pass ``null`` to clear a field, omit to leave unchanged.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `override_id` | path | string | yes | Identifier of the override. |

**Request body** (`application/json`)

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `attributes` | object | no | Free-form key/value metadata attached to this material by the organization. |
| `internal_code` | string | no | Org-internal SKU or part code for this material. |
| `material_grade_id` | string | no | Identifier of the canonical grade this override extends; null when fully org-private. |
| `notes` | string | no | Free-text notes attached to this material by the organization. |
| `trade_name` | string | no | Vendor trade name for this material (e.g. 'Inconel 718'). |
| `urn` | string | no | Canonical or org-private URN identifying the material. |

**Request**

<CodeTabs>

```bash title="cURL"
curl -X PATCH https://api.arcnm.io/api/v1/parts/materials/overrides/{override_id} \
  -H "X-API-Key: $ARCNM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "attributes": {},
    "internal_code": "string",
    "material_grade_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "notes": "string",
    "trade_name": "string",
    "urn": "string"
  }'
```

```python title="Python"
import requests

resp = requests.patch(
    "https://api.arcnm.io/api/v1/parts/materials/overrides/{override_id}",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "attributes": {},
        "internal_code": "string",
        "material_grade_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "notes": "string",
        "trade_name": "string",
        "urn": "string"
    },
)
resp.raise_for_status()
print(resp.json())
```

```typescript title="TypeScript"
const resp = await fetch("https://api.arcnm.io/api/v1/parts/materials/overrides/{override_id}", {
  method: "PATCH",
  headers: {
    "X-API-Key": process.env.ARCNM_API_KEY!,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "attributes": {},
    "internal_code": "string",
    "material_grade_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "notes": "string",
    "trade_name": "string",
    "urn": "string"
  }),
})
const data = await resp.json()
```

</CodeTabs>

**Responses**

| Status | Description |
| --- | --- |
| `200` | Successful Response |
| `422` | Validation Error |

**Errors**

Standard error responses — see the [Errors catalog](../errors.md) for the full envelope, `request_id`, and retry-safety table.

| Status | Code | When |
| --- | --- | --- |
| `401` | `invalid_api_key` | Missing, malformed, or revoked API key. |
| `403` | `insufficient_scope` | The key is valid but lacks a scope this endpoint requires. |
| `404` | `not_found` | A referenced resource doesn't exist or isn't visible to your organisation. |
| `409` | `conflict` | A conflicting change, or an `Idempotency-Key` reused with a different body. |
| `429` | `rate_limited` | Per-key or per-org rate limit exceeded — back off with jitter and retry. |


**Response body** `200`

| Field | Type | Description |
| --- | --- | --- |
| `attributes` | object | Free-form key/value metadata attached to this material by the organization. |
| `created_at` | string | Timestamp when the override was created. |
| `id` | string | Unique identifier of the override. |
| `internal_code` | string | Org-internal SKU / part code for this material. |
| `material_grade_id` | string | Identifier of the canonical grade this override extends; null when fully org-private. |
| `notes` | string | Free-text notes attached to this material by the organization. |
| `org_id` | string | Identifier of the organization that owns this override. |
| `trade_name` | string | Vendor trade name (e.g. 'Inconel 718'). |
| `updated_at` | string | Timestamp when the override was last updated. |
| `urn` | string | Canonical or org-private URN identifying the material. |

**Example response**

```json
{
  "attributes": {},
  "created_at": "2026-06-01T12:00:00Z",
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "internal_code": "string",
  "material_grade_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "notes": "string",
  "org_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "trade_name": "string",
  "updated_at": "2026-06-01T12:00:00Z",
  "urn": "string"
}
```

## List Standards

`GET /api/v1/parts/materials/standards`

**Request**

<CodeTabs>

```bash title="cURL"
curl -X GET https://api.arcnm.io/api/v1/parts/materials/standards \
  -H "X-API-Key: $ARCNM_API_KEY"
```

```python title="Python"
import requests

resp = requests.get(
    "https://api.arcnm.io/api/v1/parts/materials/standards",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
resp.raise_for_status()
print(resp.json())
```

```typescript title="TypeScript"
const resp = await fetch("https://api.arcnm.io/api/v1/parts/materials/standards", {
  method: "GET",
  headers: {
    "X-API-Key": process.env.ARCNM_API_KEY!,
  },
})
const data = await resp.json()
```

</CodeTabs>

**Responses**

| Status | Description |
| --- | --- |
| `200` | Successful Response |
| `422` | Validation Error |

**Errors**

Standard error responses — see the [Errors catalog](../errors.md) for the full envelope, `request_id`, and retry-safety table.

| Status | Code | When |
| --- | --- | --- |
| `401` | `invalid_api_key` | Missing, malformed, or revoked API key. |
| `403` | `insufficient_scope` | The key is valid but lacks a scope this endpoint requires. |
| `429` | `rate_limited` | Per-key or per-org rate limit exceeded — back off with jitter and retry. |

