GettingStarted
Dokumentation på svenska: Getting Started
The Nordomatic GraphQL API provides secure access to real-time industrial data and historical analytics.
This modern API enables you to:
- Query real-time data: Access live values and system status
- Retrieve historical data: Fetch historical data for trend analysis
- Manage authentication: Secure token-based access control
- Subscribe to live streams: Real-time data updates via GraphQL subscriptions
Prerequisites
- Valid Styrportalen account credentials (provided by your account manager)
- API endpoint URL (specific to your installation)
- Basic knowledge of GraphQL (helpful but not required)
API Architecture
Our GraphQL API follows industry best practices with a clean, intuitive structure:
- Queries: Retrieve data (no "get" prefix needed)
- Mutations: Modify data with descriptive operation prefixes
- Subscriptions: Real-time data streaming
- Comprehensive documentation: Every operation includes examples
Introspection
Introspection is available after sign-in.
Sign-in command examples can be found below in Code Examples
After successful signin, you can use introspection or download full schema.
API Access
- Endpoint: Your server-specific URL (provided with credentials)
- Interactive Playground: Built-in GraphQL explorer for testing queries
- Content Type:
application/json - Protocol: HTTPS only for security
Mockup server
A mockup server for testing and development is accessible without login at styrportalen.se/6187B2/graphql
That server has all queries and mutations as the production server but return simple "Hello world" objects.
Authentication
User Login (Sign In)
Start by authenticating with your Styrportalen credentials to establish a secure session.
Session Details:
- Duration: 7 days from login
- Security: Automatic renewal on activity
- Cookies: HTTP-only session cookies for security
Token Management
Creating Application Tokens
For production applications, create long-lived API tokens instead of using session cookies.
Token Properties:
- Label: Descriptive name for identification
- Read-only: Restrict to data access only (recommended)
- Expiration: Maximum 1 year (read-only) or 3 months (full access)
⚠️ Important Security Notice
API tokens are displayed only once during creation. Save them securely - they cannot be recovered if lost.
Token Management Operations:
userTokens: List all your tokenscreateUserToken: Generate new tokensdeleteUserToken: Permanently remove tokensrevokeUserToken: Disable specific tokensrevokeAllUserTokens: Emergency token revocation
Rate Limits
To ensure optimal performance for all users, API requests are rate-limited:
Rate Limit Policy:
- Limit: 30 requests per 60-second window
- Scope: Per ip-address
- Reset: Rolling window (not fixed intervals)
Rate Limit Headers:
Our API follows industry standards (GitHub, Stripe, Twitter) for rate limit communication:
x-ratelimit-limit: 30
x-ratelimit-remaining: 25
x-ratelimit-reset: 50
Code Examples
Authentication Examples
Initial SignIn
Authenticate using your Nordomatic credentials to establish a secure session:
mutation SignIn($username: String!, $password: String!) {
signIn(username: $username, password: $password) {
user {
username
name
email
createdAt
updatedAt
}
}
}
Variables:
{
"username": "your-username",
"password": "your-password"
}
If authentication succeeds, the server returns a session cookie:
Sessions remain active for 7 days.
Response header example.
Set-Cookie: styrportalen.session_token=...; HttpOnly; Secure
Subsequent requests must include the cookie:
Cookie: styrportalen.session_token=...
Creating Long-Lived Tokens
For production applications, create long-lived tokens instead of using session cookies:
mutation CreateUserToken($input: CreateUserTokenInput!) {
createUserToken(input: $input) {
... on CreatedUserToken {
id
readonly
expiresAt
label
token
}
... on UserTokenError {
errorMessage
}
}
}
Variables:
{
"input": {
"label": "Production App v1.0",
"readonly": false,
"expiresAt": "2024-12-31T23:59:59Z"
}
}
Token Configuration Options:
- Label: Descriptive name for easy identification
- Readonly:
truefor read-only access,falsefor full permissions - ExpiresAt: Maximum 1 year for readonly tokens, 3 months for write tokens
⚠️ Important Security Notice
API tokens are displayed only once during creation. Save them securely - they cannot be recovered if lost.
Example: TypeScript (using fetch)
const response = await fetch('https://your-api-url/graphql', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
query: `
mutation SignIn($username: String!, $password: String!) {
signIn(username: $username, password: $password) {
user {
username
name
email
createdAt
updatedAt
}
}
}`,
variables: {
username: 'your-username',
password: 'your-password',
},
}),
});
const data = await response.json();
console.log(data);
Example: Python (using requests)
import requests
url = "https://your-api-url/graphql"
query = """
mutation SignIn($username: String!, $password: String!) {
signIn(username: $username, password: $password) {
user {
username
name
email
createdAt
updatedAt
}
}
}
"""
variables = {
"username": "your-username",
"password": "your-password",
}
response = requests.post(
url,
json={
"query": query,
"variables": variables
}
)
print(response.json())
Example: C# (using HttpClient)
using System;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
var client = new HttpClient();
var url = "https://your-api-url/graphql";
var query = @"
mutation SignIn($username: String!, $password: String!) {
signIn(username: $username, password: $password) {
user {
username
name
email
createdAt
updatedAt
}
}
}";
var payload = new
{
query = query,
variables = new
{
username = "your-username",
password = "your-password"
}
};
var json = JsonSerializer.Serialize(payload);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
Example: Java (using OkHttp)
import okhttp3.*;
public class GraphQLSignInExample {
public static void main(String[] args) throws Exception {
OkHttpClient client = new OkHttpClient();
String url = "https://your-api-url/graphql";
String query = """
mutation SignIn($username: String!, $password: String!) {
signIn(username: $username, password: $password) {
user {
username
name
email
createdAt
updatedAt
}
}
}
""";
String payload = """
{
"query": "%s",
"variables": {
"username": "your-username",
"password": "your-password"
}
}
""".formatted(query.replace("\n", "\\n").replace("\"", "\\\""));
RequestBody body = RequestBody.create(
payload,
MediaType.parse("application/json")
);
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
try (Response response = client.newCall(request).execute()) {
System.out.println(response.body().string());
}
}
}
Token Management Operations
Listing Your Tokens
View all active tokens for your account:
query UserTokens {
userTokens {
tokens {
id
readonly
expiresAt
label
revoked
createdAt
lastUsedAt
lastIp
}
}
}
Token Operations
Delete a specific token:
mutation DeleteUserToken($deleteUserTokenId: ID!) {
deleteUserToken(id: $deleteUserTokenId)
}
Revoke a token (disable without deletion):
mutation RevokeUserTokens($revokeUserTokensId: ID!) {
revokeUserTokens(id: $revokeUserTokensId)
}
Emergency: Revoke all tokens:
mutation RevokeAllTokens {
revokeAllUserTokens {
count
}
}
Email Notifications
Security Monitoring
Enhance your account security by adding an email address for notifications:
mutation UpdateUserEmail($email: String!) {
updateUserEmail(email: $email)
}
What you'll receive notifications for:
- New IP address sign-ins
- Token creation
Best Practices
💡 Most integrations never hit rate limits if batch mutations are used.
To achieve optimal performance and reliability when using the Nordomatic
GraphQL API, we recommend following these best practices.
Minimize Number of Requests
GraphQL is designed to reduce the number of network roundtrips.
Whenever possible, prefer fewer requests containing more data
instead of many small requests.
✅ Recommended:
- Request multiple objects in a single query
- Perform batch updates in one mutation
- Select all required fields in one request
❌ Avoid:
- Sending multiple sequential requests for related data
- Updating objects one-by-one when they can be updated together
Example --- Preferred (Batch Writing Values):
mutation PerformWriteSignalValueByName($input: [WriteSignalValueByNameInput!]!) {
performWriteSignalValueByName(input: $input) {
... on WriteSignalSuccess {
id
displayName
}
... on WriteSignalError {
name
errorMessage
}
}
}
Variables --- Preferred (Batch Write):
{
"input": [
{
"signalName": "AHU1.SupplyTemp.Setpoint",
"value": "21.5"
},
{
"signalName": "AHU1.Fan.Start",
"value": "true"
},
{
"signalName": "Zone3.Lighting.Level",
"value": "75"
}
]
}
Instead of:
performWriteSignalValueByName(signal A)
performWriteSignalValueByName(signal B)
performWriteSignalValueByName(signal C)
Reducing requests helps you:
- Stay within rate limits
- Reduce latency
- Improve server performance
- Increase overall system reliability
Request Only the Fields You Need
GraphQL allows precise data selection. Avoid requesting unnecessary
fields.
✅ Good:
query Values($signalNames: [String!]!) {
signalValuesByName(signalNames: $signalNames) {
values {
name
value
statusCode
}
}
}
❌ Avoid requesting large objects if only small parts are needed.
Prefer Server Aggregation Over Client Loops
Avoid patterns where the client:
- Requests a list
- Loops through results
- Makes additional requests per item
Instead, structure queries so the server resolves relationships in one
request.
Handle Rate Limits Gracefully
The API enforces request rate limits per IP address.
Recommendations:
- Batch operations when possible
- Implement retry logic with backoff
- Monitor rate limit headers
x-ratelimit-remaining
x-ratelimit-reset
Reuse Authentication Tokens
For applications and integrations:
- Prefer API tokens over repeated login requests
- Avoid authenticating before every request
- Store tokens securely
Use Subscriptions for Real-Time Data
If you need continuous updates, prefer GraphQL subscriptions instead of
polling.
✅ Better:
- One subscription connection
- Server pushes updates
❌ Avoid:
- Polling queries every few seconds
Subscriptions reduce server load and network traffic significantly.
Summary
| Practice | Benefit |
|---|---|
| Batch requests | Lower latency & fewer rate limits |
| Request only needed fields | Reduced payload size |
| Use subscriptions | Efficient real-time updates |
| Reuse tokens | Better security & performance |
| Prefer logical mutations | Cleaner integrations |
Support
Getting Help
Technical Support:
- Web form: Serviceonline
- Phone: 020-365 724
© 2025 Nordomatic. All rights reserved.