1. Vad ytan gör
En incident som fångas i ert eget system behöver hamna i CyberKlar för att räknas in i rapporteringsunderlaget och i bevisen inför tillsyn. Webhooken är vägen dit för system som larmar utåt men inte kan agera API-klient: de skickar en signerad POST, och plattformen skapar incidenten.
Ska ert system i stället läsa eller uppdatera data hos oss är det det publika REST-API:et som gäller. Webhooken skriver bara in nya incidenter.
2. Adress och organisationsnyckel
Endpointen skapas i plattformen under Inställningar, och det är där ni får både adressen och signing-secreten. Adressen har formen:
POST /api/v1/webhooks/incidents/{orgKey}Organisationsnyckeln i sökvägen är inte i sig en behörighet. Anrop utan giltig signatur avvisas oavsett om nyckeln stämmer. En återkallad endpoint slutar ta emot omedelbart, utan att nycklarna för era övriga integrationer påverkas.
3. Signatur och replay-skydd
Varje anrop ska bära huvudet X-Cyberklar-Signature i formen t=<unix-tid>,v1=<hex>. Signaturen är en HMAC-SHA256 över strängen <unix-tid>.<kroppen exakt som den skickas> med er signing-secret som nyckel.
Räkna signaturen på den råa kroppen, inte på en omserialiserad version av den. Serialiserar ni om JSON efter signeringen kan blanksteg eller fältordning ändras, och då stämmer inte signaturen längre.
Tidsstämpeln jämförs mot serverns klocka och anrop utanför ett snävt tidsfönster avvisas. Det är replay-skyddet: en avlyssnad och omskickad förfrågan blir obrukbar kort efter att den fångades. Servrar som skickar till oss bör därför synkronisera klockan mot NTP, annars avvisas anropen trots korrekt secret.
Secreten lagras krypterad hos oss och kan inte läsas ut igen efter att endpointen skapats. Tappar ni bort den skapas en ny; den gamla slutar då gälla.
# Signaturen räknas över "<timestamp>.<rawBody>" med er signing-secret.
TS=$(date +%s)
BODY='{"title":"Misstänkt inloggning","description":"Fem misslyckade försök från okänd IP","severity":"high","source_system":"sentinel","external_id":"inc-4821","occurred_at":"2026-07-26T08:14:00Z"}'
SIG=$(printf '%s.%s' "$TS" "$BODY" | openssl dgst -sha256 -hmac "$CYBERKLAR_WEBHOOK_SECRET" -hex | awk '{print $2}')
curl -X POST "https://cyberklar.se/api/v1/webhooks/incidents/$CYBERKLAR_ORG_KEY" \
-H "Content-Type: application/json" \
-H "X-Cyberklar-Signature: t=$TS,v1=$SIG" \
-d "$BODY"4. Payload-format
Formatet väljs med huvudet X-Cyberklar-Format, som överstyr det format endpointen är inställd på. Tre värden stöds:
cyberklar: vår egen form, direkt nedan. Använd den om ni kontrollerar det sändande systemet.microsoft_sentinel: larm från Microsoft Sentinel skickas som de kommer, utan omskrivning hos er.generic_json: valfri JSON, där ni anger i plattformen vilket fält i er payload som motsvarar vilket fält hos oss.
{
"title": "Misstänkt inloggning",
"description": "Fem misslyckade försök från okänd IP inom två minuter.",
"severity": "high",
"source_system": "sentinel",
"external_id": "inc-4821",
"occurred_at": "2026-07-26T08:14:00Z"
}severity accepterar low, medium, high, critical och unknown. Skickar en källa något annat tolkas det som unknown i stället för att anropet avvisas, så att en okänd allvarlighetsgrad aldrig tappar bort själva incidenten. occurred_at ska vara ISO 8601.
5. Idempotens
external_id är ert eget id för händelsen och är det vi räknar dubbletter på. Skickar ni samma id igen svarar vi 200 med replay: true och skapar ingen ny incident. Det gör det säkert att sätta omsändning vid nätverksfel i ert system utan att riskera dubbletter i incidentregistret.
{ "received": true }
# Samma händelse skickad igen inom idempotensfönstret:
{ "received": true, "replay": true }6. Felkoder
| Status | Kod | Betydelse |
|---|---|---|
| 401 | unauthorized | Signaturen kunde inte verifieras, eller endpointen finns inte eller är återkallad. Samma svar ges i båda fallen, så att svaret inte avslöjar vilka organisationsnycklar som existerar. |
| 400 | invalid_json | Kroppen är inte giltig JSON. |
| 400 | invalid_format | Formatet i X-Cyberklar-Format är inte ett av de tre som stöds. |
| 413 | payload_too_large | Kroppen överskrider storleksgränsen. Skicka en sammanfattning och länka till fulla loggen i stället för att bifoga den. |
| 422 | invalid_cyberklar_payload med flera | JSON var giltig men gick inte att mappa till en incident. Svaret innehåller vilka fält som saknades eller hade fel typ. |
| 429 | rate_limited | För många anrop. Svaret bär Retry-After och X-RateLimit-*, som anger gällande kvot i realtid. |
Avvisade anrop sparas i plattformen med statuskod och ett utdrag ur kroppen, så att ni kan felsöka en misslyckad integration utan att öppna ett supportärende. Utdragen syns under Inställningar på endpointen.
7. Spårbarhet
Varje mottagen incident bär med sig var den kom ifrån, vilket är vad en granskare frågar efter: att posten kommer från ert larmsystem och inte skrevs in för hand i efterhand. Misslyckade signaturkontroller och omsändningar loggas i granskningsloggen, som är skrivskyddad i efterhand på databasnivå.
8. Support
Frågor om webhooks besvaras via support@cyberklar.se. Misstänkta sårbarheter rapporteras till security@cyberklar.se. Hur drift, arkitektur och underbiträden ser ut står på förtroendesidan.