Documentation Index
Fetch the complete documentation index at: https://docs.firstresonance.io/llms.txt
Use this file to discover all available pages before exploring further.
Overview
When you integrate against ION, eight or nine entities cover ~95% of what you’ll touch. This page walks through them top-down — what they represent, how they connect, and what they’re called in the systems you’re probably bridging from (ERP, MES, PLM, QMS).
The full schema lives in schema.graphql and the API Playground — this page is the orientation, not the reference.
Entity map
┌───────────────────┐
│ PartSubtype │ ← categorization (M2M)
└────────┬──────────┘
│ tags
┌────────▼──────────┐
│ Part │ ← catalog item (design intent)
└────────┬──────────┘
│ instances of
┌────────▼──────────┐
│ PartInventory │ ← stockable / serialized unit
└─────┬────────┬────┘
│ │
┌───────────▼─┐ ┌──▼────────────┐
│ Procedure │ │ PurchaseOrder │
│ (template)│ │ LineItems │
└───────┬─────┘ └────────────────┘
│ template for
│
┌───────▼─────┐ ┌──────────────────┐
│ Run │◀───│ RunBatch │
│ (execution) │ │ (batched runs) │
└───────┬─────┘ └──────────────────┘
│
┌───────▼─────┐ ┌──────────────────┐
│ RunStep │───▶│ BuildRequirement │
│ │ │ (aBOM line item) │
└───────┬─────┘ └──────────────────┘
│
┌───────▼─────┐
│ Issue │ ← quality event
└─────────────┘
Solid arrows are 1→many; the diagram leaves out a lot of edges (file attachments, comments, approvals) for clarity.
Parts
A Part is the catalog entry — a part number, description, revision, and the design intent. Parts are not the physical thing on the shelf; that’s PartInventory.
| Field | Notes |
|---|
id, partNumber | Org-unique within revision; partNumber is your SKU |
description | Free text |
revision | Engineering revision letter or string |
partType | part or tool |
trackingType | serial, lot, or unset (untracked) |
status | released or archived |
sourcingStrategy | make, buy, or dual_source |
purchaseType | receivable_inventory, receivable_non_inventory, or non_receivable_non_inventory |
partSubtypes | Many-to-many with PartSubtype — categorization tags |
cost, leadTime | Optional planning fields |
revisedFromId | Links this revision to its predecessor |
query GetPart {
part(id: 42) {
id
partNumber
description
revision
partType
trackingType
status
partSubtypes { id name }
}
}
Maps to: “SKU” or “Item Master” in ERP, “PartNumber” in PLM.
PartSubtype
A PartSubtype is the categorization tag attached to a Part. Subtypes are how you group parts that share routing, inspection, or planning behavior — e.g. “Mounting hardware”, “Critical-to-quality fasteners”, “Long-lead-time stock”. A part can have multiple subtypes.
query Subtypes {
partSubtypes(filters: {}, limit: 50) {
id
name
description
}
}
Maps to: “Item Family”, “Commodity Code”, or “Product Line” in ERP. Don’t confuse with revision lineage — that’s revisedFromId on Part.
PartInventory
A PartInventory is a physical instance of a Part — a serialized unit, a lot, or a quantity at a location. This is the entity that gets installed onto assemblies, consumed in runs, or shipped.
| Field | Notes |
|---|
serialNumber | If the part is serialized |
lotNumber | If the part is lot-tracked |
quantity | For non-serialized inventory (count) |
state | Available / consumed / shipped / scrapped / etc. |
part | Reference to its Part |
location | Where it physically lives |
parentPartInventory | If installed onto an assembly, points up the build tree |
entity | Polymorphic id used for file attachments, etc. |
query Inventory {
partInventory(id: 9876) {
id
serialNumber
lotNumber
quantity
state
part { id partNumber description }
location { id name }
parentPartInventory { id serialNumber }
}
}
Maps to: “Serial” or “Lot” in MES, “Inventory unit” / “Stockable item” in WMS, “Asset” in PLM.
Assemblies (as-built BOM)
An as-built BOM is the parent/child tree of PartInventory units that compose a finished assembly. ION represents this via the parentPartInventory reference on each PartInventory plus BuildRequirement records that say “to complete this assembly, install one of these parts here.”
To traverse the tree downward:
query AbomTree {
partInventory(id: 9876) {
id
serialNumber
part { partNumber }
buildRequirements {
id
part { partNumber }
quantity
installations {
id
installedPartInventory {
id
serialNumber
part { partNumber }
}
}
}
}
}
To walk up the tree, follow parentPartInventory recursively.
Maps to: “Bill of Materials” in ERP, “Assembly tree” in PLM, “Bill of Build” in MES.
mBOM vs aBOM: mBOM (manufacturing BOM) is the planned structure; aBOM (as-built) is what was actually installed at run time. Both have GraphQL types in ION; the aBOM is the post-execution truth.
Procedures and Steps
A Procedure is the manufacturing routing template — what should happen on the floor. It’s composed of Steps.
query Proc {
procedure(id: 12) {
id
title
revision
steps {
id
title
stepNumber
stepType
fields {
id
label
fieldType
}
}
}
}
Maps to: “Routing” in ERP, “Recipe” or “Standard Operating Procedure” in MES, “Work Instruction” in QMS.
Runs and RunSteps
A Run is one execution of a Procedure against a specific PartInventory. RunSteps are the per-execution instances of the procedure’s Steps — the place where operators record measurements, sign off, and report quality issues.
| Field | Notes |
|---|
id, title | |
status | Pending / In progress / Complete / etc. |
procedure | Template |
partInventory | What’s being built |
runSteps | Ordered execution instances |
runBatch | If the run participates in a batch (see Run Batches) |
query GetRun {
run(id: 1234) {
id
title
status
procedure { id title revision }
partInventory { id serialNumber part { partNumber } }
runSteps {
id
stepNumber
status
completedAt
runStepFields { id label value }
}
}
}
Maps to: “Work Order” in ERP, “Production Order” in MES, “Build” or “Job” colloquially.
Build Requirements
A BuildRequirement is a line item on an aBOM that says “to complete this assembly, install N of this part.” Operators install against build requirements during a run; each install is a row of Installations linking the PartInventory consumed to the build requirement satisfied.
See Editing Build Requirements for the user-facing flow.
Issues
An Issue is a quality event — nonconformance, deviation, supplier problem, observation. Issues attach to runs, run steps, or part inventories and follow a defined lifecycle (Pending → In Progress → In Review → Resolved). Disposition types determine what happens to the affected material.
query OpenIssues {
issues(filters: { status: "in_progress" }) {
id
title
status
issueDispositionType { id title }
assignedTo { id name }
runStep { id }
}
}
See Issue States, Dispositions, and Resolutions.
Maps to: “Nonconformance Report” (NCR) in QMS, “CAPA” precursor in QMS, “Defect” in PLM, “Incident” in ServiceNow-style systems.
Purchase Orders
For supply chain integrations:
query OpenPOs {
purchaseOrders(filters: { status: "open" }) {
id
poNumber
status
vendor { id name }
lineItems {
id
part { partNumber }
quantity
receivedQuantity
}
}
}
Maps to: “PO” in ERP. Receiving against a PO updates PartInventory records.
File Attachments
Files attach to entities polymorphically via the entity ID. See File Upload for the upload flow and the entity { id } lookup pattern.
The entity polymorphic ID
ION uses an entities table to give every attachable object a uniform ID. Most major entities expose an entity { id } field — used as the target for:
- File attachments
- Subscriptions (notifications)
- Comments
- Cross-entity links (e.g. issue-to-run-step)
Don’t confuse this with the entity’s own id. When you see an integration calling for an entityId, fetch the parent’s entity.id first.
Field-mapping cheat sheet
When you’re bridging from another system, here’s the rough translation:
| Your system says… | ION calls it… |
|---|
| SKU / Item Master / Part Number | Part.partNumber |
| Item Family / Commodity / Group | PartSubtype.name (a part can belong to multiple subtypes) |
| Lot / Batch number | PartInventory.lotNumber |
| Serial / Asset Tag | PartInventory.serialNumber |
| On-hand quantity | PartInventory.quantity |
| BOM line item | BuildRequirement |
| Work Order / Production Order | Run |
| Routing / Recipe / Process | Procedure |
| Operation / Step / Op | Step (template) / RunStep (execution) |
| NCR / Nonconformance | Issue |
| Disposition (Use As Is, Rework, Scrap) | IssueDispositionType |
| PO | PurchaseOrder |
| PO line | PurchaseOrderLineItem |
| Vendor / Supplier | PurchaseOrder.vendor (an Organization) |
| Workcenter / Cell | Location (typed WORKCENTER) |
| Tote / Bin / Rack | Location (other types) |
| User group / Role | Role |
| User | User |
| Tenant / Org | Organization |
Etag-based concurrency
Every mutable entity returns an _etag on read. Pass it back on update/delete mutations; ION rejects writes whose etag doesn’t match the current row state with a 409 (see Error Codes → 409). This is how ION prevents lost-update races.
When integrating: always read-then-write inside a short window, and propagate the etag through your service.
Discovering the rest of the schema
Three ways to find anything not on this page:
- API Playground — interactive schema explorer at /api-reference/playground
schema.graphql — committed to this repository, kept in sync with diplo
__schema introspection — programmatic access; see GraphQL Field Selection → Discovering available fields