Skip to main content

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

If you’ve ever queried ION’s API and gotten back results that looked empty — empty strings, missing IDs, null everywhere — the issue almost certainly isn’t that your data doesn’t exist. It’s that your query didn’t ask for it. GraphQL never returns fields you didn’t explicitly select. That’s a feature (you only pay for what you ask for) but it surprises every developer coming from REST, where the server decides what comes back. This page explains the model, shows the failure mode, and gives you copy-paste patterns to query ION’s most common entities completely.

Why field selection works this way

In a REST API, GET /parts/42 returns whatever the server decides — probably every column on the row. In GraphQL, you describe the response shape:
query GetPart {
  part(id: 42) {
    id
    partNumber
  }
}
The response will have exactly id and partNumber, nothing else. No description, no revision, no partSubtypes — even though those fields exist. The server only returns what was asked for. This is great for performance (you don’t pay for joins you don’t need) and great for evolution (adding fields to the schema doesn’t break anyone), but it means you have to know what you want before you query.

The blank-response trap

The most common failure mode is asking for an entity but selecting only the wrapper: Sparse query — looks like nothing came back:
query Parts {
  parts(filters: {}) {
    id
  }
}
Response — looks underwhelming:
{ "data": { "parts": [{ "id": 1 }, { "id": 2 }, { "id": 3 }] } }
You got the parts, but you’ll see “the API returned blanks for the part numbers” because you didn’t ask for partNumber. Add the fields you actually need: Complete query:
query Parts {
  parts(filters: {}) {
    id
    partNumber
    description
    revision
    partType
    status
    partSubtypes {
      id
      name
    }
  }
}
Response — now you have something useful:
{
  "data": {
    "parts": [
      {
        "id": 1,
        "partNumber": "BRKT-001",
        "description": "Mounting bracket, aluminum",
        "revision": "B",
        "partType": "part",
        "status": "released",
        "partSubtypes": [{ "id": 7, "name": "Mounting hardware" }]
      }
    ]
  }
}
If you find yourself debugging “the API isn’t returning my data,” the first thing to check is your selection set.

Selecting nested objects

Nested objects (relationships) need their own field selections — the same rule applies recursively. Querying a relationship without selecting any of its fields is a syntax error in GraphQL:
query PartWithSubtypes {
  part(id: 42) {
    id
    partSubtypes {     # invalid — must select fields inside partSubtypes
    }
  }
}
You have to select at least one field on the related object:
query PartWithSubtypes {
  part(id: 42) {
    id
    partSubtypes {
      id
      name
    }
  }
}
This applies all the way down the tree — querying a run’s current step’s procedure means selecting fields on each level.

Patterns for ION’s main entities

Here are minimum-viable field selections for the entities you’ll touch most. Drop these into your queries when you don’t yet know what you’ll need — easier to remove fields later than to chase down “why is this blank.”

Parts

fragment PartFields on Part {
  id
  partNumber
  description
  revision
  partType
  status
  partSubtypes { id name }
}

Part Inventory (a stockable instance of a part)

fragment PartInventoryFields on PartInventory {
  id
  serialNumber
  lotNumber
  quantity
  state
  part { ...PartFields }
  location { id name }
}

Runs

fragment RunFields on Run {
  id
  title
  status
  startedAt
  completedAt
  procedure { id title revision }
  partInventory { ...PartInventoryFields }
}

Purchase Orders

fragment PurchaseOrderFields on PurchaseOrder {
  id
  status
  vendor { id name }
  lineItems {
    id
    quantity
    part { ...PartFields }
  }
}

Issues

fragment IssueFields on Issue {
  id
  title
  status
  issueDispositionType { id title }
  assignedTo { id name }
}

Using fragments for reusable selections

A fragment is a named selection set you can reuse across queries. They keep your client code DRY and make field-selection consistency easy to enforce.
fragment PartFields on Part {
  id
  partNumber
  description
  revision
  partType
  status
  partSubtypes { id name }
}

query Parts {
  parts(filters: {}, limit: 50) {
    ...PartFields
  }
}

query PartByNumber {
  partsByNumber(partNumber: "BRKT-001") {
    ...PartFields
  }
}
Both queries return identical part shapes. If you need to start including revision everywhere, you change the fragment in one place. In a Python or JavaScript client, define each fragment once at module load and compose it into queries — see the Python Quickstart for an end-to-end pattern.

Discovering available fields

Three ways to find out what fields an entity has:

1. Use the schema explorer in the API Playground

The Mintlify API Playground embeds the live ION GraphQL schema. Click into any type to see every field, its return type, its arguments, and its description.

2. Run an introspection query

GraphQL has a built-in introspection mechanism — query the schema itself to enumerate types:
query SchemaForPart {
  __type(name: "Part") {
    name
    fields {
      name
      type { name kind }
    }
  }
}
This works against any GraphQL endpoint, including yours, and is what most GraphQL tooling uses internally.

3. Read the schema file

The full schema is committed to this repository as schema.graphql and synced from the production diplo schema (see Mintlify API Playground for the sync workflow). Open the file in your editor to grep for types and fields by hand.

Tips

  • Start broad, narrow as you go. When prototyping a new query, request more fields than you think you need. After the integration is working, trim the selection set down to what your code actually uses.
  • Use fragments to enforce consistency. If three queries return parts, all three should use the same fragment. Avoids the “this query returns revision but that one doesn’t” inconsistency that bites integrations later.
  • Watch for nullable fields. Many ION fields are nullable (description, revision, etc.). Selecting them isn’t enough — your code must handle the null case.
  • __typename is free. Adding __typename to a selection set helps when you parse polymorphic responses or want to assert at runtime that you got back what you expected.