GettingStarted

Dokumentation på engelska: Getting Started

Nordomatics GraphQL API ger säker åtkomst till realtidsdata och historisk analys för industriella system.
Med detta moderna API kan du:

  • Hämta realtidsdata: Få tillgång till aktuella värden och systemstatus
  • Hämta historisk data: Hämta historik för trendanalys
  • Hantera autentisering: Säker token-baserad åtkomstkontroll
  • Prenumerera på live-strömmar: Realtidsuppdateringar via GraphQL subscriptions

Förutsättningar

  • Giltiga Styrportalen-inloggningsuppgifter (fås av din kontaktperson)
  • API-endpoint URL (specifik för din installation)
  • Grundläggande kunskap om GraphQL (hjälpsamt men inte nödvändigt)

API-arkitektur

Vårt GraphQL API följer branschstandarder med en tydlig och intuitiv struktur:

  • Queries: Hämta data (utan "get"-prefix)
  • Mutations: Ändra data med beskrivande operationer
  • Subscriptions: Realtidsströmning av data
  • Omfattande dokumentation: Alla operationer har exempel

Introspection

Introspection är tillgänglig efter lyckad inloggning.
Login examples återfinns i Kodexempel
Efter lyckad inlogging går det också att ladda ner komplett schema.

API-åtkomst

  • Endpoint: Din serverspecifika URL (fås med inloggningsuppgifter)
  • Interaktiv Playground: Inbyggd GraphQL-explorer för att testa queries
  • Content-Type: application/json
  • Protokoll: Endast HTTPS för säkerhet

Mockup-server

En mockup-server för test och utveckling finns tillgänglig utan inloggning på styrportalen.se/6187B2/graphql
Den servern har samma queries och mutations som produktionsservern men returnerar enkla "Hello world"-objekt.

Autentisering

Användarinloggning (Sign In)

Börja med att logga in med dina Styrportalen-uppgifter för att skapa en säker session.

Sessionsdetaljer:

  • Varaktighet: 7 dagar från inloggning
  • Säkerhet: Automatisk förnyelse vid aktivitet
  • Cookies: HTTP-only sessionscookies för säkerhet

Tokenhantering

Skapa applikationstokens

För produktionsapplikationer, skapa långlivade API-tokens istället för att använda sessionscookies.

Tokenegenskaper:

  • Label: Beskrivande namn för identifiering
  • Read-only: Begränsa till endast läsning (rekommenderas)
  • Utgång: Max 1 år (read-only) eller 3 månader (full åtkomst)

⚠️ Viktigt säkerhetsmeddelande

API-tokens visas endast en gång vid skapande. Spara dem säkert – de kan inte återställas om de tappas bort.

Tokenhanteringsoperationer:

  • userTokens: Lista alla dina tokens
  • createUserToken: Skapa nya tokens
  • deleteUserToken: Ta bort tokens permanent
  • revokeUserToken: Inaktivera specifika tokens
  • revokeAllUserTokens: Nödlägesåterkallelse av alla tokens

Anropsbegränsning (Rate Limits)

För att säkerställa optimal prestanda för alla användare är API-förfrågningar anropsbegränsade:

Policy för rate limit:

  • Gräns: 30 förfrågningar per 60 sekunder
  • Scope: Per ip-adress
  • Återställning: Rullande fönster (ej fasta intervall)

Rate limit-headrar:
Vårt API följer branschstandard (GitHub, Stripe, Twitter) för rate limit-kommunikation:

x-ratelimit-limit: 30
x-ratelimit-remaining: 25
x-ratelimit-reset: 50

Kodexempel

Exempel på autentisering

Inloggning

Autentisera med dina Nordomatic-uppgifter för att skapa en säker session.

mutation SignIn($username: String!, $password: String!) {
  signIn(username: $username, password: $password) {
    user {
      username
      name
      email
      createdAt
      updatedAt
    }
  }
}

Variabler:

{
  "username": "your-username",
  "password": "your-password"
}

Om autentiseringen lyckas returnerar servern en sessionscookie.
Sessionen hålls aktiv i 7 dagar.
Exempel på svarshuvud:

Set-Cookie: styrportalen.session_token=...; HttpOnly; Secure  

Efterföljande anrop måste inkludera cookien:

Cookie: styrportalen.session_token=...

Skapa långlivade tokens

För produktionsapplikationer, skapa långlivade tokens istället för att använda sessionscookies:

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"
  }
}

Tokenkonfigurationsalternativ:

  • Label: Beskrivande namn för enkel identifiering
  • Readonly: true för endast läsbehörighet, false för fulla rättigheter
  • ExpiresAt: Max 1 år för readonly-tokens, 3 månader för skriv-tokens

⚠️ Viktigt säkerhetsmeddelande

API-tokens visas endast en gång vid skapande. Spara dem säkert – de kan inte återställas om de tappas bort.


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());
    }
  }
}

Tokenhanteringsoperationer

Lista dina tokens

Visa alla aktiva tokens för ditt konto:

query UserTokens {
  userTokens {
    tokens {
      id
      readonly
      expiresAt
      label
      revoked
      createdAt
      lastUsedAt
      lastIp
    }
  }
}

Tokenoperationer

Ta bort en specifik token:

mutation DeleteUserToken($deleteUserTokenId: ID!) {
  deleteUserToken(id: $deleteUserTokenId)
}

Återkalla en token (inaktivera utan att ta bort):

mutation RevokeUserTokens($revokeUserTokensId: ID!) {
  revokeUserTokens(id: $revokeUserTokensId)
}

Nödläge: Återkalla alla tokens:

mutation RevokeAllTokens {
  revokeAllUserTokens {
    count
  }
}

E-postnotifieringar

Säkerhetsövervakning

Förbättra din kontosäkerhet genom att lägga till en e-postadress för notifieringar:

mutation UpdateUserEmail($email: String!) {
  updateUserEmail(email: $email)
}

Du får notifieringar om:

  • Inloggning från ny IP-adress
  • Skapande av token

Best Practices

💡 De flesta integrationer når aldrig rate limits om batch-mutations används.

För att uppnå bästa möjliga prestanda och stabilitet vid användning av Nordomatic GraphQL API rekommenderar vi följande riktlinjer.

Minimera antal förfrågningar

GraphQL är utformat för att minska antalet nätverksanrop.
När det är möjligt bör du föredra färre förfrågningar som innehåller mer data istället för många små anrop.

✅ Rekommenderas:

  • Hämta flera objekt i samma query
  • Utför batch-uppdateringar i en mutation
  • Begär alla nödvändiga fält i ett och samma anrop

❌ Undvik:

  • Flera sekventiella requests för relaterad data
  • Att uppdatera objekt ett i taget när de kan skickas tillsammans

Exempel — Rekommenderat (Batch-skrivning):

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"
    }
  ]
}

istället för:

performWriteSignalValueByName(signal A)
performWriteSignalValueByName(signal B)
performWriteSignalValueByName(signal C)

Att minska antalet requests hjälper dig att:

  • Hålla dig inom rate limits
  • Minska latens
  • Förbättra serverprestanda
  • Öka systemets stabilitet

Begär endast de fält du behöver

GraphQL gör det möjligt att exakt välja vilken data som ska returneras.
Undvik att begära fler fält än nödvändigt.

✅ Bra exempel:

query Values($signalNames: [String!]!) {
  signalValuesByName(signalNames: $signalNames) {
    values {
      name
      value
      statusCode
    }
  }
}

❌ Undvik att hämta stora objekt om endast delar av informationen behövs.


Låt servern aggregera data istället för klienten

Undvik mönster där klienten:

  1. Hämtar en lista
  2. Loopar igenom resultatet
  3. Gör ytterligare requests per objekt

Strukturera istället queries så att servern returnerar all relaterad data i ett anrop.

Instead, structure queries so the server resolves relationships in one
request.


Hantera rate limits korrekt

API:et begränsar antal requests per IP-adress.

Rekommendationer:

  • Batcha operationer när det är möjligt
  • Implementera retry-logik med backoff
  • Övervaka rate limit-headers
x-ratelimit-remaining
x-ratelimit-reset

Återanvänd autentiseringstokens

För applikationer och integrationer:

  • Använd API-tokens istället för upprepade inloggningar
  • Undvik att autentisera före varje request
  • Lagra tokens säkert

Använd Subscriptions för realtidsdata

Om du behöver kontinuerliga uppdateringar bör GraphQL subscriptions användas istället för polling.

✅ Bättre:

  • En aktiv subscription-anslutning
  • Servern skickar uppdateringar automatiskt

❌ Undvik:

  • Polling-queries varannan sekund

Subscriptions minskar både serverbelastning och nätverkstrafik avsevärt.


Sammanfattning

Rekommendation Fördel
Batcha requests Lägre latens och färre rate limits
Begär endast nödvändiga fält Mindre datamängd
Använd subscriptions Effektiva realtidsuppdateringar
Återanvänd tokens Bättre säkerhet och prestanda
Använd logiska mutations Renare och stabilare integrationer

Support

Få hjälp

Teknisk support:


© 2025 Nordomatic. Alla rättigheter förbehållna.