Exsitec Data Link

Rå ↓ — Rå Markdown för AI-assistenter

Exsitec Data Link — Användning

Exsitec Data Link är en liten Windows-kompanjon som låter ett lokalt program — en Excel-arbetsbok, ett skript eller ditt eget verktyg — köra Visma Business NXT GraphQL- queries och mutations utan att själv hantera Visma-inloggning eller token. Den loggar in i Business NXT åt dig och exponerar en styrd GraphQL-gateway på din egen dator (localhost): du skickar ett GraphQL-dokument, Data Link kontrollerar dina Data Link- rättigheter för varje företag som dokumentet berör och vidarebefordrar det till Business NXT under din egen Visma-inloggning. Svaret från Business NXT returneras oförändrat.

Läser du detta med en AI-assistent? Den här sidan är den kompletta användningsreferensen. Du kan klistra in den i din assistent, eller ge den rå Markdown på /docs/usage.md?lang=sv (samma innehåll, utan formatering). Be den skriva anropen på det språk du föredrar — allt den behöver (endpoints, headers, rättighetsregler, request- och response-format samt felformat) finns nedan. För själva Business NXT-schemat (tabeller, fält, filter), peka den mot Vismas Business NXT GraphQL-dokumentation eller be den köra en introspection-query genom gatewayen.


1. Kom igång snabbt

  1. Installera och logga in. Installera Data Link och högerklicka sedan på dess tray-ikon (nere till höger, nära klockan) → Logga in. Webbläsaren öppnar Visma Connect; logga in där.

  2. Hitta porten och nyckeln. Läs %LOCALAPPDATA%\Exsitec\DataLink\endpoint.json — den innehåller loopback-port och en key som skapas vid varje start.

  3. Säg hej. GET http://127.0.0.1:{port}/v1/status med headern X-DataLink-Key: {key}. Du får versionen och om du är inloggad.

  4. Välj ett företag. GET /v1/companies listar företagen du kan komma åt, med vad din Data Link-åtkomst och dina behörigheter låter dig göra i varje företag.

  5. Kör GraphQL. POST /v1/nxt/graphql med en standard GraphQL-body:

    { "query": "{ useCompany(no: 4926238) { generalLedgerAccount(first: 5) { items { accountNo name } } } }" }
    

    Svaret är Business NXT:s egen { "data": …, "errors": … }.


2. Så körs den

Var saker finns

Vad Var
Discovery-fil (port + nyckel) %LOCALAPPDATA%\Exsitec\DataLink\endpoint.json — kan bara läsas av dig.
Loggar %LOCALAPPDATA%\Exsitec\DataLink\logs\ (tray → Öppna loggmapp). Loggar innehåller aldrig GraphQL-dokument, belopp, nycklar eller tokens.
Inloggningssession session.dat i samma mapp, krypterad för din Windows-användare.
Själva appen %LOCALAPPDATA%\Exsitec.DataLink\ (per användare-installation som uppdaterar sig själv).

3. Prata med det lokala API:et

Discovery — hitta porten och nyckeln

Kompanjonen väljer en ledig loopback-port vid start och skriver en liten discovery- fil så att betrodda lokala anropare kan hitta den:

%LOCALAPPDATA%\Exsitec\DataLink\endpoint.json
{
  "port": 51234,
  "key": "b3d1…a9f0",
  "instanceId": "3f2a…",
  "processId": 18244,
  "protocol": "v1",
  "version": "2.0.0",
  "startedUtc": "2026-10-07T07:15:00.0000000+00:00"
}

Bas-URL och versionering

http://127.0.0.1:{port}/v1/…

Alla endpoints ligger under prefixet /v1 (fältet protocol i discovery- filen); GraphQL-gatewayen är /v1/nxt/graphql. Bind mot 127.0.0.1 (loopback) — kompanjonen lyssnar bara där.

Obligatoriska request-headers

Header När Värde
X-DataLink-Key Varje request key från endpoint.json.
Content-Type: application/json Requests med JSON-body Skicka bodyn som UTF-8.

Det finns ingen företagsheader: företaget anges inne i GraphQL-dokumentet.

Svarsrubriker

Header Betydelse
X-DataLink-Instance Kompanjonens instanceId för denna körning.

Omstartssignal. Om värdet i X-DataLink-Instance ändras mellan anrop har kompanjonen startat om. Läs endpoint.json på nytt — både porten och nyckeln kan ha ändrats.

Tidsgränser

Säkerhetsbegränsningar (varför en webbläsar-fetch avvisas)

Kompanjonen upprätthåller en trust boundary för loopback:


4. Endpoint-referens

Varje request behöver X-DataLink-Key. Response-bodys från själva Data Link är JSON med fältnamn i camelCase; POST /v1/nxt/graphql returnerar Business NXT:s body oförändrad.

Metod Sökväg Syfte
GET /v1/status Hälsa, version och inloggningsstatus.
POST /v1/auth/login Interaktiv webbläsarinloggning.
POST /v1/auth/logout Avsluta Business NXT-sessionen.
GET /v1/companies Företag som inloggningen kan komma åt, med dina rättigheter i varje.
POST /v1/nxt/graphql Valfri Business NXT GraphQL-query eller mutation, rättighetskontrollerad.

GET /v1/status

Hälsa och inloggningsstatus. Den fungerar även när du är utloggad.

{
  "status": "ok",
  "instanceId": "3f2a…",
  "protocol": "v1",
  "version": "2.0.0",
  "provider": { "id": "business-nxt", "authenticated": true },
  "startedUtc": "2026-10-07T07:15:00+00:00"
}

POST /v1/auth/login

Startar den interaktiva webbläsarinloggningen och returnerar när den är klar. Ingen body. Den öppnar alltid webbläsaren, även när du redan är inloggad — kontrollera GET /v1/status först om du bara vill logga in vid behov.

{ "authenticated": true }

Om webbläsarflödet inte slutförs inom 5 minuter misslyckas anropet med 503 unavailable (retryable: true); en inloggning som Visma Connect avvisar returnerar 401 unauthorized.

POST /v1/auth/logout

Avslutar Business NXT-sessionen. Returnerar { "authenticated": false }.

GET /v1/companies

Företagen som den aktuella inloggningen kan komma åt (Business NXT:s availableCompanies), varje med sin tenant (Visma.net-kunden det tillhör) och den Data Link-åtkomst och de behörigheter som gäller där — så att du kan slå upp ett företags namn till dess nummer och se vad du får göra innan du försöker.

{
  "available": [
    { "id": "4926238", "name": "Exsitec BNXT Demo",         "tenantId": "4926230", "canRead": true, "canWrite": false, "canDelete": false },
    { "id": "6307615", "name": "Demo - Junge Byg Aps 9999", "tenantId": "2728812", "canRead": true, "canWrite": true,  "canDelete": false }
  ]
}

Ett företag som listas med canRead: false är ett företag som din Visma-inloggning kan se men som Data Link inte öppnar för dig (se avsnitt 5).

POST /v1/nxt/graphql — gatewayen

Kör valfri Business NXT GraphQL-query eller mutation. Bodyn är standard GraphQL-over-HTTP:

{
  "query": "query Accounts($company: Int!) { useCompany(no: $company) { generalLedgerAccount(first: 5) { items { accountNo name } } } }",
  "variables": { "company": 4926238 },
  "operationName": "Accounts"
}
Fält Obligatoriskt Betydelse
query ja GraphQL-dokumentet (sträng).
variables nej Ett JSON-objekt med variabelvärden.
operationName nej Vilken operation som ska köras när dokumentet har flera.
extensions nej Standard GraphQL extension-data, vidarebefordras oförändrad. Rättighetskontrollen läser den inte.

Vad som händer:

  1. Data Link parsar dokumentet och räknar ut varje företag det läser, skriver eller tar bort i (avsnitt 6).
  2. Den kontrollerar din Data Link-åtkomst och dina behörigheter för vart och ett. Om något inte är tillåtet avvisas hela dokumentet och inget når Business NXT.
  3. Annars vidarebefordrar den din request-body oförändrad till Business NXT under din Visma-inloggning och returnerar Business NXT:s HTTP-status och body ordagrant — inklusive Business NXT:s egna errors och extensions (till exempel extensions.vbnxt-trace-id).
{
  "data": {
    "useCompany": {
      "generalLedgerAccount": {
        "items": [ { "accountNo": 1010, "name": "Varesalg DK" }, { "accountNo": 1020, "name": "Anden omsætning" } ]
      }
    }
  },
  "extensions": { "vbnxt-trace-id": "…" }
}

Data Link förnyar din Visma-token själv och, när Business NXT svarar 429 Too Many Requests, väntar och försöker igen — båda är säkra eftersom requesten inte kördes. Den försöker aldrig igen med något annat, så en mutation kan aldrig köras två gånger; ett 5xx från Business NXT skickas tillbaka till dig som det är.


Vad du får göra genom Data Link administreras av Exsitec i NxtPlatform admin. Den gamla Config API-portalen för behörighetstilldelning är borta; docs/download-värden ger inte åtkomst.

Vad Tilldelas Tillåter
Data Link-åtkomst Per tenant (en Visma.net-kund) genom Data Link-modulen — för alla användare eller valda grupper, med åsidosättning per användare. Läsning av valfritt företag i den tenant (canRead). Utan den avvisas allt på tenantens företag, även läsningar.
Skriv-behörighet Genom NxtPlatform-roller. Mutations som skapar, uppdaterar, processar eller rapporterar (*_create, *_update, *_processings, *_reports, edit-cache-kontroll) — på tenants där du har Data Link-åtkomst (canWrite).
Radera-behörighet Genom NxtPlatform-roller. Mutations som raderar (*_delete) — på tenants där du har Data Link-åtkomst (canDelete). Radering kräver Radera, inte Skriv.

Data Link begränsar bara vad din egen Visma-användare får göra — den ger aldrig åtkomst som Visma inte skulle ge. Ett företag utanför dina availableCompanies avvisas även om du har åtkomst till dess tenant.

När du inte har Skriv-behörighet någonstans ber Data Link också Visma om en read-only-inloggning nästa gång du loggar in, så Business NXT själv avvisar mutations också.

Din åtkomst och dina behörigheter hämtas från NxtPlatform när du loggar in och uppdateras med några minuters mellanrum, och sparas bara i minnet. Om NxtPlatform inte kan nås fortsätter det senaste svaret att gälla under en kort respitperiod; efter det — eller om Data Link aldrig har nått NxtPlatform sedan den startade — avvisar gatewayen med 503 unavailable (retryable: true) i stället för att köra okontrollerat.


6. Så läser rättighetskontrollen ett dokument

Kontrollen arbetar med det parsade dokumentet, aldrig med dess text, så alias, fragments och variabler kan inte dölja något. Den är avsiktligt strikt:

Ange företaget: useCompany(no: {companyNo})

Varje företagsavgränsad läsning eller skrivning ligger under roten useCompany(no: …). no är företagsnumret från GET /v1/companies — en literal, en variabel eller ett variabel-defaultvärde:

query Projects($company: Int!) {
  useCompany(no: $company) {
    orgUnit2(filter: { orgUnit2No: { _eq: 2130 } }) { items { orgUnit2No name } }
  }
}

(Business NXT:s organisatoriska enheter får nya etiketter per företag; i Demo - Junge Byg Aps 9999 är projekt orgUnit2.)

Vad varje del av ett dokument kräver

I dokumentet Kräver
query { useCompany(no: N) { … } } Läsning på företag N:s tenant.
mutation { useCompany(no: N) { x_create / x_update / x_processings / x_reports / finishEditCache … } } Skrivning på N:s tenant.
mutation { useCompany(no: N) { x_delete … } } Radering på N:s tenant.
query { useCustomer(no: T) { … } } Läsning på tenant T.
mutation { useCustomer(…) } Avvisas alltid — ändringar på kundnivå (användare, företag) görs inte genom Data Link.
mutation { asyncQuery(query: "…", args: {…}) } Det som det inbäddade dokumentet kräver, kontrollerat med samma regler.
availableCompanies, availableCustomers, useModel, api, asyncRequests, asyncResult, asyncQuery_delete, introspection (__schema, __type) Endast en inloggning.
Alla andra rotfält, eller en subscription Avvisas (403 forbidden).

Skriv säkert

Business NXT har inga transaktioner över flera tabeller. Två vanor gör en skrivning förutsägbar:


7. Fel

Det finns två slags fel, och båda använder GraphQL:s felformat.

Business NXT:s egna fel — ett GraphQL-fel, ett värde som Business NXT avvisar, en rate limit — kommer tillbaka exakt som Business NXT skickade dem: dess HTTP-status och body { "data": …, "errors": [ … ] }.

Avslag från Data Link själv (requesten nådde aldrig Business NXT) har extensions.code:

{
  "errors": [
    {
      "message": "You have no Data Link Write permission for company 'Exsitec BNXT Demo' (4926238).",
      "extensions": { "code": "forbidden", "retryable": false, "instanceId": "3f2a…", "company": "4926238" }
    }
  ]
}
code HTTP Betydelse / vad du ska göra
invalid_request 400 Bodyn är inte JSON, saknar query, har medlemmar utöver query/variables/operationName/extensions eller upprepade property-namn (även om de bara skiljer sig i skiftläge), variables är inte ett objekt, dokumentet kan inte parsas, eller ett företagsnummer kan inte lösas. Rätta och skicka igen.
unauthorized 401 Saknad/ogiltig nyckel, inte inloggad, eller Visma avvisade inloggningen. Läs endpoint.json på nytt; logga in.
forbidden 403 Din Data Link-åtkomst eller dina behörigheter tillåter inte detta på ett företag (extensions.company anger det), företaget är inte tillgängligt för dig, eller dokumentet använder en avvisad root (useCustomer mutation, okänd root, subscription). Även cross-origin-/host-blockeringar.
unavailable 503 Dina rättigheter kunde inte hämtas (retryable: true), eller Data Link är upptagen. Försök igen snart.
internal_error 500 Oväntat. Kontrollera loggmappen (tray → Öppna loggmapp).

GET /v1/status, /v1/auth/* och GET /v1/companies rapporterar sina fel i Data Links vanliga envelope i stället:

{ "code": "unauthorized", "message": "…", "retryable": false, "instanceId": "3f2a…" }

En okänd sökväg får en enkel 404.


8. Relation till Business NXT GraphQL API

Data Link är Business NXT:s GraphQL API, nått via din egen dator:


9. Använda den från Excel

Ladda ned och importera de två VBA-modulerna nedan (Alt+F11 -> Arkiv -> Importera fil...). De är standardmoduler och använder bara late binding, så inga ändringar i Verktyg -> Referenser behövs.

Fil Vad den är
ExsitecDataLink.bas Det fasta SDK:t: auto-start, discovery, inloggning, GraphQL, JSON, fel och utskrift till kalkylblad.
ExsitecDataLinkCustom.bas Din arbetsboksmall: COMPANY_NO och exempel på knappmakron. Ändra den här filen per kund/arbetsbok.

Publikt VBA-API

API Syfte
NxtQuery(gql, [vars]) As Object Skickar en GraphQL-query eller mutation till POST /v1/nxt/graphql och returnerar data-ordlistan. Om dokumentet använder $company och vars saknar company, lägger SDK:t till COMPANY_NO.
NxtVars(name, value, ...) As Object Bygger en variabelordlista. Exempel: NxtVars("company", 4926238, "first", 20).
NxtItems(data, path) As Collection Går en punktseparerad path som useCompany.generalLedgerAccount och returnerar dess items-collection. items: null blir en tom collection.
WriteRows(items, target, [columns], [includeHeader]) As Range Skriver rader till Excel i ett block. Nästlade objekt expanderas en nivå (a.b), ISO-datum blir Excel-datum, null blir tomt och text som ser ut som formler förblir text.
ShowNxtError() Visar Err.Description i en vänlig meddelanderuta. Använd den i felhanterare.
NxtUseEndpointFile(path) Avancerad/test-hook för en discovery-fil som inte är standard.
NxtUseLanguage(languageCode) Avancerad/test-hook som åsidosätter SDK:ts meddelandespråk (en, da, sv, nb).
NxtUseStartPaths(primaryExe, fallbackExe) Avancerad/test-hook för Data Link-körbara sökvägar som inte är standard.

Mönster för knappmakron

Lägg företagsspecifika inställningar och knappmakron i ExsitecDataLinkCustom.bas:

Public Const COMPANY_NO As Long = 4926238

Public Sub ListAccounts()
    On Error GoTo Failed
    Dim data As Object
    Set data = NxtQuery("query Accounts($company: Int!) { useCompany(no: $company) { generalLedgerAccount(first: 20) { items { accountNo name } } } }")
    WriteRows NxtItems(data, "useCompany.generalLedgerAccount"), ActiveSheet.Range("A1"), Array("accountNo", "name")
    Exit Sub
Failed:
    ShowNxtError
End Sub

För mutations anropar du samma NxtQuery-funktion med ett mutation-dokument. SDK:t försöker aldrig köra mutations igen efter en portändring eller ett transportfel.

Auto-start och inloggning

SDK:t läser %LOCALAPPDATA%\Exsitec\DataLink\endpoint.json. Om filen saknas eller /v1/status inte svarar startar det %LOCALAPPDATA%\Exsitec.DataLink\Exsitec Data Link.exe (eller current\DesktopDataLink.Host.exe) och väntar upp till 30 sekunder.

Före varje anrop kontrollerar det /v1/status. Om du är utloggad talar Excel om att webbläsaren kommer att öppnas, anropar /v1/auth/login och kastar sedan ett fel som säger att du ska köra åtgärden igen när inloggningen är klar. Den ursprungliga GraphQL-requesten körs inte automatiskt efter inloggning.

VBA-felnummer

Konstant Betydelse
NXT_ERR_NOT_RUNNING Data Link är inte installerad, kunde inte startas eller svarade aldrig.
NXT_ERR_NOT_SIGNED_IN Du är utloggad, avbröt inloggningen, eller inloggningen kräver att åtgärden körs igen.
NXT_ERR_FORBIDDEN Data Link-åtkomst/behörigheter förbjuder requesten eller företaget.
NXT_ERR_INVALID GraphQL-requesten är felaktigt formad eller tillåts inte av gatewayen.
NXT_ERR_NXT Business NXT returnerade GraphQL-fel; Err.Description är det första Business NXT-meddelandet.
NXT_ERR_UNAVAILABLE Data Link, Business NXT eller rättighetstjänsten är tillfälligt otillgänglig.
NXT_ERR_OTHER Alla andra responses som inte är lyckade.

Meddelanden använder Data Link-trayens språkinställning (ui-settings.json) för engelska, danska, svenska och norska, med engelska som standard.


10. Exempel i andra språk

PowerShell

# 1. Discover the running companion.
$ep   = Get-Content "$env:LOCALAPPDATA\Exsitec\DataLink\endpoint.json" | ConvertFrom-Json
$base = "http://127.0.0.1:$($ep.port)/v1"
$hdr  = @{ "X-DataLink-Key" = $ep.key }

# 2. Check status / sign-in.
Invoke-RestMethod "$base/status" -Headers $hdr

# 3. Resolve a company name to its number, and see your rights there.
$companies = (Invoke-RestMethod "$base/companies" -Headers $hdr).available
$company   = $companies | Where-Object { $_.name -eq "Exsitec BNXT Demo" }

# 4. Run GraphQL.
$body = @{
    query     = 'query A($c: Int!) { useCompany(no: $c) { generalLedgerAccount(first: 5) { items { accountNo name } } } }'
    variables = @{ c = [int]$company.id }
} | ConvertTo-Json -Depth 5

$result = Invoke-RestMethod "$base/nxt/graphql" -Method Post -Headers $hdr `
    -ContentType "application/json" -Body $body
$result.data.useCompany.generalLedgerAccount.items

Python

Endast standardbibliotek:

import json, os, urllib.request

path = os.path.join(os.environ["LOCALAPPDATA"], "Exsitec", "DataLink", "endpoint.json")
with open(path, encoding="utf-8-sig") as f:
    ep = json.load(f)
base = f"http://127.0.0.1:{ep['port']}/v1"

def call(method, path, body=None):
    headers = {"X-DataLink-Key": ep["key"]}
    data = None
    if body is not None:
        data = json.dumps(body).encode("utf-8")
        headers["Content-Type"] = "application/json"
    request = urllib.request.Request(base + path, data=data, headers=headers, method=method)
    with urllib.request.urlopen(request, timeout=300) as response:   # HTTPError carries the GraphQL errors
        return json.load(response)

def graphql(query, **variables):
    return call("POST", "/nxt/graphql", {"query": query, "variables": variables})

companies = call("GET", "/companies")["available"]
junge = next(c for c in companies if c["name"] == "Demo - Junge Byg Aps 9999")

result = graphql(
    "query P($c: Int!, $p: Int!) { useCompany(no: $c) { orgUnit2(filter: { orgUnit2No: { _eq: $p } }) { items { orgUnit2No name } } } }",
    c=int(junge["id"]), p=2130)
print(result["data"]["useCompany"]["orgUnit2"]["items"])

11. Felsökning

Symptom Trolig orsak Vad du ska göra
Ingen endpoint.json, eller VBA NXT_ERR_NOT_RUNNING Data Link är inte installerad eller svarade inte. VBA-SDK:t startar den automatiskt; om det misslyckas, installera den från docs/download-sidan.
Anslutningen nekas efter att den fungerade tidigare Data Link startade om eller avslutades (t.ex. efter en uppdatering): ny port och ny nyckel. Läs endpoint.json på nytt.
401 "A valid connector key is required." Nyckeln saknas eller är inaktuell. Läs endpoint.json på nytt — nyckeln ändras vid varje start.
401 "Not signed in to Business NXT…" Du är inte inloggad, eller sessionen har avslutats. Tray → Logga in (eller POST /v1/auth/login).
403 "Cross-origin requests are not permitted." Anropet kom från JavaScript i webbläsaren. Anropa från ett lokalt program eller skript i stället.
403 "You have no Data Link Access to …" Du saknar Data Link-åtkomst på det företagets tenant. Be din Exsitec-kontakt om Data Link-åtkomst till den tenanten.
403 "You have no Data Link Write / Delete permission…" Dina NxtPlatform-roller saknar den behörigheten (canWrite / canDelete). Be din Exsitec-kontakt; kontrollera GET /v1/companies.
403 "Company … is not available to the signed‑in user." Din Visma-användare kan inte se det företaget, eller så finns ett skrivfel i numret. Kontrollera GET /v1/companies; logga ut och in med rätt Visma-användare.
400 "…'no' argument must resolve to an integer." useCompany utan nummer, eller en variabel som du inte skickade. Skicka företagsnumret som en Int-literal eller variabel.
503 "Data Link rights could not be fetched…" NxtPlatform kan inte nås. Försök igen snart.
503 "Sign-in timed out…" Webbläsarinloggningen slutfördes inte inom 5 minuter. Försök igen och slutför den i webbläsaren.
Excel visar "Svarar inte" under inloggning /v1/auth/login väntar på webbläsaren. Slutför inloggningen i webbläsaren och kör sedan Excel-åtgärden igen.

Fortfarande fast? Tray → Öppna loggmapp och skicka den senaste loggfilen till din Exsitec-kontakt — den innehåller inga GraphQL-dokument, belopp, nycklar eller tokens.


12. Ordlista

Term Betydelse
Data Link (kompanjon) Tray-appen på din dator som loggar in i Business NXT och tillhandahåller den lokala gatewayen.
NXT Gateway POST /v1/nxt/graphql: Business NXT GraphQL, rättighetskontrollerad och vidarebefordrad under din inloggning.
Rättighetskontroll Gatewayens kontroll av ett parsat GraphQL-dokument mot din Data Link-åtkomst och dina behörigheter, allt eller inget.
Data Link-åtkomst Din rätt att över huvud taget använda Data Link på en tenants företag (canRead), tilldelad i NxtPlatform admins Data Link-modul.
Data Link-behörighet Skriv eller Radera (canWrite / canDelete), tilldelad genom NxtPlatform-roller; den gäller bara på tenants där du har Data Link-åtkomst.
Tenant En Visma.net-kund; Data Link-åtkomst tilldelas per tenant.
Företag Ett Business NXT-företag, identifierat med sitt nummer och namngivet i varje dokument med useCompany(no: …).
Discovery-fil endpoint.json: där den körande Data Link publicerar sin port, nyckel och instance id.
Nyckel Hemligheten som skapas vid varje start och som varje request måste bära; den ändras vid varje start.
Instance id Identifierar en körning av Data Link; ett nytt värde betyder att den har startat om.

Det här dokumentet beskriver det lokala v1-API:et. Kompanjonen rapporterar sin körande version i GET /v1/status och i tray-menyn.

↑ Toppen