WorkAround API v1
Portal Logg inn
Versjon 1.0

API-dokumentasjon

Referanse for WorkAround sin webhook- og portal-API. Brukes til å sende hendelser inn i systemet og integrere med tredjepartsverktøy.

Oversikt

WorkAround tilbyr to typer API-tilgang:

  • Webhook API – Eksternt system poster hendelser til WorkAround (inngående). Brukes av overvåkings­systemer, alarmsentraler og ERP-systemer.
  • Portal API – Programmatisk innsending av kundeforespørsler.

Base-URL

Base-URL
https://workaround.nettbook.no

Innholdstype

Alle API-kall bruker Content-Type: application/json med UTF-8-koding. Svar returneres alltid som JSON.

Bruk alltid HTTPS i produksjon. Serveren kjører TLS 1.2+.

Autentisering

Webhook-endepunkt

Webhook-endepunktet er åpent for inngående POST uten autentisering. Vi anbefaler å sikre det med én av disse metodene:

  • HMAC-SHA256 – Legg til en delt hemmelighet og send signaturen i headeren X-Signature: sha256=<hex>.
  • IP-hvitelisting – Begrens tilgang til kjente avsender-IP-adresser på nettverksnivå.
  • API-nøkkel – Send X-Api-Key: <nøkkel>. Konfigureres per integrasjon i admin-panelet.
Merk: Send ikke sensitive personopplysninger (personnummer, passord, bankdata) via webhook-endepunktet.

Portal-endepunkt

Portal-innsending krever en gyldig CSRF-token. For automatiserte integrasjoner, se callout om alternativ fremgangsmåte under Portal API.

Feilhåndtering

Feil returneres som JSON med feltene error og message:

Feilrespons
{
  "error":   "validation_failed",
  "message": "Feltet 'sender_email' er påkrevd",
  "fields": {
    "sender_email": "Mangler verdi"
  }
}
StatuskodeKodeBeskrivelse
202acceptedWebhook mottatt og lagt i kø
400empty_payloadTomt eller manglende body
400validation_failedUgyldig eller manglende felt
403csrf_mismatchCSRF-token mangler eller ugyldig
404not_foundRessursen finnes ikke
500server_errorIntern feil – prøv igjen etter en stund
Bruk eksponensiell backoff ved 5xx-feil (1 s → 2 s → 4 s → 8 s). Ikke prøv automatisk på nytt ved 4xx – det er en klientfeil.

Inngående webhook

Send hendelser fra eksterne systemer til WorkAround. Hendelsene lagres i integrasjonsloggen og kan utløse automatiserte regler.

POST /api/webhook/{system}

URL-parameter

ParameterTypeBeskrivelse
system påkrevd string Identifikator for avsendersystemet. Kun a–z, 0–9, bindestrek og understrek. Eks: scada, alarm-central, erp

Headers

HeaderBeskrivelse
Content-Type påkrevd application/json
X-Event-Type valgfritt Hendelsestype for filtrering i loggen. Eks: alarm.trigger, device.offline
X-Signature valgfritt HMAC-SHA256 signatur: sha256=<hex-digest>

Request body

Body er fri JSON. Anbefalt struktur for best integrasjon:

Anbefalt payload
{
  "event":     "alarm.trigger",         // hendelsestype
  "timestamp": "2026-04-09T08:14:00Z", // ISO 8601
  "source":    "SCADA-node-047",         // kilde-ID
  "severity":  "high",               // low|medium|high|critical
  "data": {
    "node_id":            "N-201",
    "description":        "Fiberbrudd på linje 3",
    "location": { "lat": 59.4130, "lng": 5.2680 },
    "affected_customers": 142
  },
  "metadata": {
    "correlation_id": "abc-12345"
  }
}

Hendelsestyper

X-Event-TypeTypisk brukstilfelle
alarm.triggerAlarm utløst (SCADA, NMS)
alarm.clearAlarm kvittert / opphørt
device.offlineNode eller enhet er utilgjengelig
device.onlineNode eller enhet er tilbake online
workorder.createdArbeidsordre opprettet i eksternt system
workorder.updatedArbeidsordre oppdatert i eksternt system
customer.complaintKlage rapportert av kunde
maintenance.scheduledPlanlagt vedlikehold fra ekstern kalender

Respons

202 Accepted
{ "accepted": true }
400 Bad Request – tomt body
{ "error": "Empty payload" }

Portal API

Sender en kundeforespørsel programmatisk, tilsvarende nettskjemaet på /portal.

POST /portal
Endepunktet krever en gyldig _csrf-token. For maskin-til-maskin-integrasjoner anbefaler vi webhook-endepunktet i stedet.

Felt (application/x-www-form-urlencoded)

FeltTypeBeskrivelse
_csrf påkrevdstringCSRF-token fra GET /portal
form_template_slug påkrevdstringSkjematype-slug fra admin-panelet. Eks: fiber-utfall
sender_name påkrevdstringFullt navn på innsender
sender_email påkrevdstringE-postadresse. Bekreftelse sendes hit.
sender_phone valgfrittstringTelefonnummer
subject påkrevdstringEmne/tittel (maks 255 tegn)
description påkrevdstringDetaljert beskrivelse
extra[*] valgfrittmixedTilleggsfelter definert av det valgte skjemaet

Respons

Vellykket innsending gir HTTP 200 med HTML-side som viser saksnummeret (format: PR-YYYY-NNNN). Innsender mottar e-postbekreftelse automatisk.

Eksempel: cURL

Alarm-hendelse fra SCADA

bash
curl -X POST \
  https://workaround.nettbook.no/api/webhook/scada \
  -H "Content-Type: application/json" \
  -H "X-Event-Type: alarm.trigger" \
  -d '{
    "event": "alarm.trigger",
    "timestamp": "2026-04-09T08:14:00Z",
    "source": "SCADA-node-047",
    "severity": "high",
    "data": {
      "node_id": "N-201",
      "description": "Fiberbrudd på linje 3",
      "location": { "lat": 59.4130, "lng": 5.2680 },
      "affected_customers": 142
    }
  }'

Enhet offline fra NMS

bash
curl -X POST \
  https://workaround.nettbook.no/api/webhook/nms \
  -H "Content-Type: application/json" \
  -H "X-Event-Type: device.offline" \
  -d '{
    "event": "device.offline",
    "timestamp": "2026-04-09T09:02:17Z",
    "source": "OLT-Haugesund-3",
    "data": {
      "device_id": "OLT-003",
      "ip": "10.100.3.5",
      "ports_affected": 48
    },
    "metadata": { "correlation_id": "nms-evt-78432" }
  }'

Planlagt vedlikehold fra ERP

bash
curl -X POST \
  https://workaround.nettbook.no/api/webhook/erp \
  -H "Content-Type: application/json" \
  -H "X-Event-Type: maintenance.scheduled" \
  -d '{
    "event": "maintenance.scheduled",
    "data": {
      "title": "Fiberskjøting Strandgaten 12–18",
      "area": "Haugesund sentrum",
      "planned_start": "2026-04-14T07:00:00",
      "planned_end":   "2026-04-14T15:00:00",
      "technician": "Ola Nordmann",
      "work_order_ref": "WO-20245"
    }
  }'

Eksempel: Python

Enkel innsending

python
import requests
from datetime import datetime, timezone

BASE = "https://workaround.nettbook.no"

def send_alarm(node_id, description, severity="high"):
    payload = {
        "event":     "alarm.trigger",
        "timestamp": datetime.now(timezone.utc).isoformat(),
        "source":    f"node-{node_id}",
        "severity":  severity,
        "data":      {"node_id": node_id, "description": description},
    }
    r = requests.post(
        f"{BASE}/api/webhook/scada",
        json=payload,
        headers={"X-Event-Type": "alarm.trigger"},
        timeout=10,
    )
    r.raise_for_status()
    return r.json()

# Bruk
send_alarm("N-201", "Fiberbrudd på linje 3", "critical")

Med retry og eksponensiell backoff

python
import requests, time, logging

def send_with_retry(url, payload, max_attempts=4):
    for attempt in range(max_attempts):
        try:
            r = requests.post(url, json=payload, timeout=10)
            if r.status_code == 202:
                return True
            if 400 <= r.status_code < 500:
                logging.error(f"Klientfeil {r.status_code}: {r.text}")
                return False  # ikke prøv igjen
        except requests.RequestException as e:
            logging.warning(f"Forsøk {attempt + 1} feilet: {e}")
        time.sleep(2 ** attempt)   # 1s, 2s, 4s, 8s
    return False

Eksempel: Node.js

Med fetch (Node 18+)

javascript
const BASE = 'https://workaround.nettbook.no';

async function sendWebhook(system, eventType, payload) {
  const r = await fetch(`${BASE}/api/webhook/${system}`, {
    method:  'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-Event-Type': eventType,
    },
    body:   JSON.stringify(payload),
    signal: AbortSignal.timeout(10000),
  });
  if (!r.ok) throw new Error(`${r.status}: ${await r.text()}`);
  return r.json();
}

// Bruk
sendWebhook('nms', 'device.offline', {
  event:  'device.offline',
  source: 'OLT-003',
  data:   { ip: '10.100.3.5', ports_affected: 48 },
}).then(console.log).catch(console.error);

Med HMAC-SHA256 signatur

javascript (Node.js)
const crypto = require('crypto');
const axios  = require('axios');

const SECRET = process.env.WA_WEBHOOK_SECRET;

function sign(body) {
  return 'sha256=' + crypto.createHmac('sha256', SECRET).update(body).digest('hex');
}

async function sendSigned(system, eventType, payload) {
  const body = JSON.stringify(payload);
  return axios.post(`https://workaround.nettbook.no/api/webhook/${system}`, body, {
    headers: {
      'Content-Type': 'application/json',
      'X-Event-Type': eventType,
      'X-Signature':  sign(body),
    },
    timeout: 10000,
  });
}

HTTP-statuskoder

KodeNavnNår?
200OKForespørselen behandlet (portal HTML-svar)
202AcceptedWebhook mottatt og lagt i kø
400Bad RequestTomt body, ugyldig JSON eller manglende felt
403ForbiddenCSRF-token mangler eller ugyldig
404Not FoundEndepunktet finnes ikke
405Method Not AllowedFeil HTTP-metode
500Internal Server ErrorIntern feil – loggføres automatisk
503Service UnavailableServer midlertidig utilgjengelig

Endringslogg

VersjonDatoEndring
v1.0 April 2026 Første versjon. Inngående webhook (POST /api/webhook/{system}) og portal-innsending (POST /portal).
Spørsmål om integrasjon? Kontakt teknisk drift: noreply@nettbook.no. Hendelseslogg og integrasjonsstatus finner du i admin-panelet under Administrasjon → Integrasjoner.