Skip to main content

Query root

All queries are scoped to a site via the required siteId parameter (multi-tenant architecture).
type Query {
  # List queries (return all results)
  building(siteId: String!, id: String, name: String, nameMatch: NameMatch): [Building!]!
  equipment(siteId: String!, id: String, name: String, nameMatch: NameMatch, locationId: String, locationName: String, systemId: String, is: String, hasProperty: String, propertyValue: String): [Equipment!]!
  point(siteId: String!, id: String, name: String, nameMatch: NameMatch, equipmentId: String, locationId: String, locationName: String, zoneId: String, systemId: String, is: String, equipmentIs: String, hasProperty: String, propertyValue: String): [Point!]!
  zone(siteId: String!, id: String, name: String, nameMatch: NameMatch, locationId: String, is: String, hasProperty: String, propertyValue: String): [Zone!]!
  system(siteId: String!, name: String, nameMatch: NameMatch, is: String, hasProperty: String, propertyValue: String): [System!]!

  # Single-entity lookup
  location(siteId: String!, locationId: String!): Location

  # Cross-reference
  entityByIfcId(siteId: String!, ifcId: String!): KgEntity
}

Enums

NameMatch

Controls how name and locationName arguments are matched against entity labels.
enum NameMatch {
  CONTAINS   # Case-insensitive substring match (default)
  EXACT      # Exact string match
}
ModeBehaviorWhen to use
CONTAINS"AHU" matches “TE01-XX-AHU-001”, “AHU-Rooftop”Discovery, search, AI agents (you don’t know the exact name)
EXACT"TE01-XX-AHU-001" matches only that exact stringPrecision lookups (you already know the name, no false positives)
CONTAINS is the default. You only need to specify nameMatch: EXACT when precision matters.

Shared types

EntityProperty

Static metadata about an entity (design capacity, manufacturer, rated power, etc.). These are characteristics that rarely change, as opposed to Points which model live telemetry.
type EntityProperty {
  name: String!    # Property key (e.g., "designedAirFlow", "manufacturer")
  value: String!   # Property value (e.g., "5000", "Carrier")
  unit: String     # Unit of measurement if applicable (e.g., "L/s", "kW")
}

Object types

Building

type Building {
  uri: String!
  id: ID!
  name: String!
  type: String!
  ifcId: String
  locations(name: String, nameMatch: NameMatch, is: String, recursive: Boolean = false): [Location!]!
  equipment(name: String, nameMatch: NameMatch, is: String, recursive: Boolean = false): [Equipment!]!
  zones(name: String, nameMatch: NameMatch, is: String, recursive: Boolean = false): [Zone!]!
  systems(name: String, nameMatch: NameMatch, is: String, recursive: Boolean = false): [System!]!
  points(name: String, nameMatch: NameMatch, is: String, recursive: Boolean = false): [Point!]!
  properties: [EntityProperty!]!
}

Equipment

type Equipment {
  uri: String!
  id: ID!
  name: String!
  type: String!
  typeHierarchy: [String!]!
  ifcId: String
  points(name: String, nameMatch: NameMatch, is: String): [Point!]!
  parts(name: String, nameMatch: NameMatch, is: String): [Equipment!]!
  partOf: Equipment
  feeds(name: String, nameMatch: NameMatch, is: String): [Equipment!]!
  fedBy(name: String, nameMatch: NameMatch, is: String): [Equipment!]!
  upstream(maxDepth: Int, medium: String, is: String): [Equipment!]!
  downstream(maxDepth: Int, medium: String, is: String): [Equipment!]!
  location: Location
  systems: [System!]!
  properties: [EntityProperty!]!
}

Point

type Point {
  uri: String!
  id: ID!
  name: String!
  type: String!
  typeHierarchy: [String!]!
  unit: String
  equipmentId: String!
  timeseriesId: String
  writable: String
  valueType: String
  currentValue: PointValue
  equipment: Equipment
  location: Location
  properties: [EntityProperty!]!
}
currentValue returns the latest reading (last 5 minutes). Only resolved when requested in the query, so there is no performance cost if omitted. Returns null if timeseriesId is null or no recent data exists. For historical timeseries data (time ranges, aggregation, charts), use the timeseries REST API with timeseriesIds.

PointValue

type PointValue {
  value: Float
  timestamp: String
  quality: String
}
FieldTypeDescription
valueFloatThe latest sensor reading (nullable, null if no data)
timestampStringISO-8601 timestamp in the site’s local timezone (e.g., 2026-03-03T14:30:00+00:00 for London)
qualityString"good" if value is present AND less than 5 minutes old; "stale" if no value or older than 5 minutes; "unknown" if the timestamp cannot be parsed

Location

type Location {
  uri: String!
  id: ID!
  name: String!
  type: String!
  ifcId: String
  parent: Location
  locations(name: String, nameMatch: NameMatch, is: String, recursive: Boolean = false): [Location!]!
  equipment(name: String, nameMatch: NameMatch, is: String, recursive: Boolean = false): [Equipment!]!
  points(name: String, nameMatch: NameMatch, is: String, recursive: Boolean = false): [Point!]!
  zones: [Zone!]!
  properties: [EntityProperty!]!
}

Zone

type Zone {
  uri: String!
  id: ID!
  name: String!
  type: String!
  typeHierarchy: [String!]!
  ifcId: String
  locations: [Location!]!
  fedBy(name: String, nameMatch: NameMatch, is: String): [Equipment!]!
  upstream(maxDepth: Int, medium: String, is: String): [Equipment!]!
  points(name: String, nameMatch: NameMatch, is: String): [Point!]!
  properties: [EntityProperty!]!
}

System

type System {
  uri: String!
  id: ID!
  name: String!
  type: String!
  ifcId: String
  equipment(name: String, nameMatch: NameMatch, is: String, recursive: Boolean = false): [Equipment!]!
  points(name: String, nameMatch: NameMatch, is: String, recursive: Boolean = false): [Point!]!
  properties: [EntityProperty!]!
}

Union types

KgEntity

Union of all knowledge graph entity types. Returned by entityByIfcId for BIM-to-KG cross-referencing.
union KgEntity = Building | Equipment | Location | Zone | System
Use inline fragments to select fields based on the returned type:
{
  entityByIfcId(siteId: "your-site-id", ifcId: "2JF4e6axWHqu3u0C1FZlmi") {
    ... on Equipment { id name type ifcId points { id name currentValue { value } } }
    ... on Location  { id name type ifcId }
    ... on Building  { id name type ifcId }
    ... on Zone      { id name type ifcId }
    ... on System    { id name type ifcId }
  }
}
Returns null when the IFC GlobalId is not mapped to any Tacit entity. This is expected for IFC elements that have no corresponding knowledge graph entry (e.g., structural columns, ductwork segments).