Documentation Index
Fetch the complete documentation index at: https://docs.sensorup.com/llms.txt
Use this file to discover all available pages before exploring further.
Core Platform Guide
The Core Platform API provides foundational services that underpin all SensorUp operations. It includes authentication (su-auth), user management (su-user), core infrastructure (su-backend), geospatial services (su-maps), data catalogs (su-catalog), and event streaming (su-eventhub).
Overview
The Core Platform enables:
- Authentication: Session management, API keys, and federated sign-in
- User Management: User profiles, permissions, and device tracking
- Geospatial Services: Maps, location queries, and spatial operations
- Data Catalogs: Schema registry and metadata management
- Event Streaming: Real-time event subscriptions and notifications
- Core Infrastructure: Configuration, health checks, and system operations
Authentication (su-auth)
For comprehensive authentication documentation, see the Authentication Guide.
Quick Reference
Session-based Authentication:
mutation SignIn($input: AuthSignInInput!) {
signIn(input: $input) {
session {
username
authenticated
expiresAt
expiresAtHard
userGroup
}
correlationId
errors { message type }
}
}
Check Current Session:
query {
session {
username
authenticated
expiresAt
userGroup
lastAuthenticatedAt
}
}
API Key Creation:
mutation CreateAPIKey($input: AuthCreateAPIKeyInput!) {
createAPIKey(input: $input) {
apiKey {
apiKeyId
apiKeySessionId
expiresAt
}
correlationId
errors { message type }
}
}
Session Lifetimes
| Client Type | Hard Expiry | Soft Expiry (Idle) |
| Explorer (Web) | 30 days | 7 days |
| SensorHub Android | 365 days | 60 days |
| SensorHub iOS | 365 days | 60 days |
| API Key | 365 days | 60 days |
Authentication Methods
- Cookie:
sensorup_sessionid (auto-set in browser)
- Header:
x-sensorup-sessionid (for API clients and M2M)
curl -X POST https://customer-demo.sensorup.com/api/graphql \
-H "Content-Type: application/json" \
-H "x-sensorup-sessionid: YOUR_SESSION_ID" \
-d '{"query":"{ session { username } }"}'
User Management (su-user)
Query User Profile
query GetUser($userId: ID!) {
user(id: $userId) {
userId
username
email
firstName
lastName
phoneNumber
preferredLanguage
timezone
groups
permissions {
resource
actions
}
devices {
deviceKey
name
remembered
lastSignedInAt
lastIpAddress
}
}
}
Update User Profile
mutation UpdateUser($input: UpdateUserInput!) {
updateUser(input: $input) {
user {
userId
firstName
lastName
email
phoneNumber
}
correlationId
errors {
message
type
}
}
}
Variables:
{
"input": {
"userId": "user-123",
"firstName": "John",
"lastName": "Smith",
"phoneNumber": "+1-555-0100",
"timezone": "America/Edmonton"
}
}
Query User Permissions
query GetUserPermissions($userId: ID!) {
user(id: $userId) {
userId
username
groups
permissions {
resource
actions
scope
}
roles {
roleId
roleName
permissions {
resource
actions
}
}
}
}
List Users in Group
query GetGroupUsers($group: ID!) {
users(group: $group) {
all(first: 100) {
edges {
node {
userId
username
email
firstName
lastName
active
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
}
Device Management
query GetUserDevices($userId: ID!) {
user(id: $userId) {
devices {
deviceKey
name
remembered
createdAt
lastSignedInAt
lastIpAddress
userAgent
}
}
}
Forget Device:
mutation ForgetDevice($input: AuthForgetSpecificDevicesInput!) {
forgetDevices(input: $input) {
session {
username
}
correlationId
errors { message type }
}
}
Geospatial Services (su-maps)
Query Map Configuration
query GetMapConfig {
maps {
config {
defaultCenter {
lat
lon
}
defaultZoom
baseLayers {
id
name
type
url
attribution
}
overlayLayers {
id
name
type
url
}
}
}
}
Get Map Tiles
query GetMapTiles($bounds: BoundsInput!, $zoom: Int!) {
maps {
tiles(bounds: $bounds, zoom: $zoom) {
tileUrl
bounds {
north
south
east
west
}
zoom
}
}
}
Variables:
{
"bounds": {
"north": 51.1,
"south": 51.0,
"east": -114.0,
"west": -114.1
},
"zoom": 12
}
Geocoding
query Geocode($address: String!) {
maps {
geocode(address: $address) {
results {
formattedAddress
geometry {
location {
lat
lon
}
bounds {
north
south
east
west
}
}
placeId
types
}
}
}
}
Variables:
{
"address": "Calgary, Alberta, Canada"
}
Reverse Geocoding
query ReverseGeocode($lat: Float!, $lon: Float!) {
maps {
reverseGeocode(lat: $lat, lon: $lon) {
results {
formattedAddress
addressComponents {
longName
shortName
types
}
placeId
}
}
}
}
Variables:
{
"lat": 51.0447,
"lon": -114.0719
}
Spatial Queries
query FindNearbyAssets($location: LocationInput!, $radiusKm: Float!) {
maps {
findNearby(location: $location, radius: $radiusKm) {
results {
id
type
distance
geometry {
type
coordinates
}
properties
}
}
}
}
Variables:
{
"location": {
"lat": 51.0447,
"lon": -114.0719
},
"radiusKm": 10.0
}
GeoJSON Support
The platform supports full GeoJSON geometry types:
type GeoJSONGeometry {
type: GeoJSONType! # Point, LineString, Polygon, etc.
coordinates: GeoJSONCoordinates
bbox: [Float]
}
enum GeoJSONType {
Point
MultiPoint
LineString
MultiLineString
Polygon
MultiPolygon
GeometryCollection
Feature
FeatureCollection
}
Example Point:
{
"type": "Point",
"coordinates": [-114.0719, 51.0447]
}
Example Polygon:
{
"type": "Polygon",
"coordinates": [[
[-114.073, 51.045],
[-114.071, 51.045],
[-114.071, 51.044],
[-114.073, 51.044],
[-114.073, 51.045]
]]
}
Data Catalogs (su-catalog)
Query Catalog Entries
query GetCatalogEntries {
catalog {
entries(first: 100) {
edges {
node {
id
name
description
schema
dataType
category
tags
createdAt
updatedAt
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
}
Get Specific Catalog Entry
query GetCatalogEntry($id: ID!) {
catalog {
entry(id: $id) {
id
name
description
schema
dataType
category
tags
metadata
validationRules {
rule
message
}
}
}
}
Create Catalog Entry
mutation CreateCatalogEntry($input: CreateCatalogEntryInput!) {
createCatalogEntry(input: $input) {
catalogEntry {
id
name
schema
}
correlationId
errors {
message
type
}
}
}
Variables:
{
"input": {
"id": "pressure-reading",
"name": "Pressure Reading",
"description": "Equipment pressure sensor reading",
"dataType": "numeric",
"schema": {
"type": "object",
"properties": {
"value": { "type": "number" },
"unit": { "type": "string", "enum": ["psi", "kPa", "bar"] },
"timestamp": { "type": "string", "format": "date-time" }
},
"required": ["value", "unit", "timestamp"]
},
"category": "sensor-data",
"tags": ["pressure", "sensor", "telemetry"]
}
}
Query by Category
query GetCatalogByCategory($category: String!) {
catalog {
byCategory(category: $category) {
id
name
description
dataType
}
}
}
Variables:
{
"category": "sensor-data"
}
Event Streaming (su-eventhub)
Subscribe to Events
subscription OnEvents($filter: EventFilter) {
events(filter: $filter) {
eventId
eventType
source
timestamp
data
correlationId
}
}
Variables (Filter by Event Type):
{
"filter": {
"eventTypes": ["ASSET_CREATED", "ASSET_UPDATED", "ISSUE_CREATED"]
}
}
Publish Event
mutation PublishEvent($input: PublishEventInput!) {
publishEvent(input: $input) {
event {
eventId
eventType
timestamp
}
correlationId
errors {
message
type
}
}
}
Variables:
{
"input": {
"eventType": "CUSTOM_EVENT",
"source": "integration-service",
"data": {
"action": "data_sync_completed",
"recordsProcessed": 1500,
"duration": 45.2
}
}
}
Query Event History
query GetEventHistory($filter: EventFilter!, $first: Int!) {
eventHub {
history(filter: $filter, first: $first) {
edges {
node {
eventId
eventType
source
timestamp
data
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
}
Variables:
{
"filter": {
"eventTypes": ["ASSET_CREATED"],
"from": "2025-11-01T00:00:00Z",
"to": "2025-11-05T23:59:59Z"
},
"first": 100
}
Event Types
Common system event types:
| Event Type | Description |
ASSET_CREATED | New asset created |
ASSET_UPDATED | Asset modified |
ASSET_DELETED | Asset removed |
ISSUE_CREATED | New issue opened |
ISSUE_UPDATED | Issue modified |
ISSUE_CLOSED | Issue resolved and closed |
DETECTION_CREATED | New detection recorded |
FORM_SUBMITTED | XForm response submitted |
USER_SIGNED_IN | User authentication |
API_KEY_CREATED | New API key generated |
Core Infrastructure (su-backend)
System Configuration
query GetConfig {
config {
environment
version
features {
name
enabled
configuration
}
auth {
loginEnabled
ssoEnabled
ssoUrl
mfaRequired
}
integrations {
name
type
endpoint
active
}
}
}
Health Check
query HealthCheck {
health {
status
version
timestamp
services {
name
status
latency
lastCheck
}
}
}
Feature Flags
query GetFeatureFlags {
features {
all {
featureId
name
enabled
rolloutPercentage
conditions {
type
value
}
}
}
}
Check Specific Feature:
query IsFeatureEnabled($featureId: ID!, $context: FeatureContext) {
features {
isEnabled(featureId: $featureId, context: $context)
}
}
System Metrics
query GetSystemMetrics {
metrics {
apiCalls {
total
byEndpoint {
endpoint
count
avgLatency
}
}
errors {
total
byType {
type
count
}
}
performance {
avgResponseTime
p95ResponseTime
p99ResponseTime
}
}
}
Common Patterns
Authentication Flow
// 1. Sign in
const { data } = await client.mutate({
mutation: SIGN_IN,
variables: {
input: {
loginUsername: 'user@example.com',
password: 'password',
clientApplicationType: 'EXPLORER'
}
}
})
// 2. Store session ID
const sessionId = data.signIn.session.sessionId
// 3. Use in subsequent requests
const result = await fetch('https://customer-demo.sensorup.com/api/graphql', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-sensorup-sessionid': sessionId
},
body: JSON.stringify({ query: '{ session { username } }' })
})
Geospatial Queries
// Find assets near a location
async function findAssetsNearLocation(lat, lon, radiusKm) {
const { data } = await client.query({
query: FIND_NEARBY,
variables: { location: { lat, lon }, radiusKm }
})
return data.maps.findNearby.results
}
// Geocode an address
async function getCoordinates(address) {
const { data } = await client.query({
query: GEOCODE,
variables: { address }
})
return data.maps.geocode.results[0].geometry.location
}
Event Streaming
// Subscribe to real-time events
const subscription = client.subscribe({
query: ON_EVENTS,
variables: {
filter: {
eventTypes: ['ASSET_CREATED', 'ISSUE_CREATED']
}
}
}).subscribe({
next: ({ data }) => {
console.log('New event:', data.events)
handleEvent(data.events)
},
error: (error) => console.error('Subscription error:', error)
})
// Cleanup
subscription.unsubscribe()
// Use catalog to validate form data
async function validateFormData(dataType, data) {
// Get schema from catalog
const { data: catalogData } = await client.query({
query: GET_CATALOG_ENTRY,
variables: { id: dataType }
})
const schema = catalogData.catalog.entry.schema
// Validate against schema
const valid = validateAgainstJsonSchema(data, schema)
return valid
}
Best Practices
1. Session Management
Monitor session expiration and refresh proactively:
// Check session expiration
const { data } = await client.query({ query: GET_SESSION })
const expiresAt = new Date(data.session.expiresAt)
const now = new Date()
// Refresh if expiring soon (within 1 hour)
if (expiresAt - now < 3600000) {
await refreshSession()
}
Use appropriate zoom levels and bounds for map tiles:
# Good - reasonable bounds
maps { tiles(bounds: { ... }, zoom: 12) }
# Avoid - excessive detail over large area
maps { tiles(bounds: { ... }, zoom: 18) }
3. Event Filtering
Subscribe only to needed event types:
# Good - filtered subscription
subscription { events(filter: { eventTypes: ["ASSET_CREATED"] }) }
# Avoid - unfiltered (high volume)
subscription { events }
4. Catalog Validation
Leverage catalog schemas for data validation:
# 1. Get schema from catalog
catalog { entry(id: "sensor-reading") { schema } }
# 2. Validate data client-side before submission
# 3. Submit validated data
5. Permission Checks
Always verify user permissions before restricted operations:
query CheckPermission($userId: ID!, $resource: String!, $action: String!) {
user(id: $userId) {
permissions {
resource
actions
}
}
}
Error Handling
Platform mutations return consistent error formats:
{
"data": {
"updateUser": {
"user": null,
"correlationId": "abc-123",
"errors": [
{
"message": "Invalid email address format",
"type": "VALIDATION_ERROR"
}
]
}
}
}
Common error types:
AUTHENTICATION_FAILED: Invalid credentials
AUTHORIZATION_FAILED: Insufficient permissions
VALIDATION_ERROR: Input validation failed
NOT_FOUND: Resource does not exist
DUPLICATE: Resource already exists
RATE_LIMIT_EXCEEDED: Too many requests