Skip to main content Link Menu Expand (external link) Copy Copied

Ons API Webhooks in je integratie gebruiken

Ons API Webhooks stelt externe integraties in staat om notificaties te ontvangen van gebeurtenissen (wijzigingen in de data van applicaties) in de Ons Suite.

Usecases

Er zijn twee veelvoorkomende situaties waarbij het handig is om Ons API Webhooks te gebruiken:

Een gesynchroniseerde dataset onderhouden voor gebruik in je integratie

Na het eenmalig ophalen van alle gegevens (bijvoorbeeld via /t/employees/x-stream-connect/data), kun je vervolgens up-to-date blijven door je te abonneren op alle event types voor Employee en ze te verwerken zodra ze binnenkomen. Zonder webhooks zou je regelmatig moeten controleren op de /t/employees/x-stream-connect/updates en /t/employees/x-stream-connect/deletes endpoints, en zelfs bij het controleren om de 5 minuten zou je altijd een beetje achterlopen.

Reageren op gebeurtenissen binnen de Ons Suite

Bijvoorbeeld, de volgende stap nadat een medewerker een Client aanmaakt in Ons zou kunnen zijn om een bepaalde actie uit te voeren in je geïntegreerde systeem, maar dit kan alleen worden gedaan nadat die Client is gesynchroniseerd.

  • Zonder webhooks moet die gebruiker wachten tot de volgende geplande synchronisatie of zelf een handmatige synchronisatie starten. Dit is geen goede gebruikerservaring.
  • Met webhooks kan de Client gesynchroniseerd worden met je geïntegreerde systeem tegen de tijd dat de gebruiker is overgeschakeld.

Hoe webhooks te gebruiken

Abonneren

Om je te abonneren op webhooks, moeten er vier stappen worden voltooid:

  1. Genereer een secret op de pagina van jouw koppeling (zie Afbeelding 1). Dit secret wordt gebruikt om de Hash-based Message Authentication Code (HMAC) te verifiëren. Hoe dit te implementeren, staat verder beschreven in authenticatie.

  2. Zorg ervoor dat er een POST endpoint - dat in staat is om notificaties te ontvangen - beschikbaar is op het URL dat je wil gebruiken voor webhooks. Dit endpoint moet een 200 OK status terug sturen bij een correcte HMAC, en een 401 UNAUTHORIZED bij een incorrecte HMAC. Om te verifiëren dat dit goed is geïmplementeerd, zullen er tijdens het configureren van je URL twee NOP events verstuurd worden. Hierbij heeft er één een correcte HMAC heeft, en één een incorrecte HMAC (lees NOP-event).

  3. Configureer de webhooks-URL’s voor je integratie in het Ons API-dashboard op de pagina van jouw koppeling. Dit zullen drie URL’s zijn, een voor iedere omgeving (development, staging en production). Alle versies van jouw koppeling zullen gebruik maken van deze URL’s. Meer specifieke routing moet worden gedaan aan de kant van de integratie. Webhook-url configuratie Afbeelding 1.

  4. Selecteer in de versie die webhook-abonnementen vereist alle combinaties van Model en event-types die interessant zijn voor de integratie en sla deze vervolgens op. Je geselecteerde webhook-abonnementen maken deel uit van de review die wordt uitgevoerd vóór het volgende ontwikkelstadium kan worden bereikt. Selectie-element voor webhook-abonnementen Afbeelding 2.

Vanwege redundantie en caching in onze webhook-service kan het tot 5 minuten duren nadat je hebt opgeslagen voordat je op een betrouwbare manier begint (of stopt) met het ontvangen van geselecteerde events. Je zal alleen events ontvangen van klanten omgevingen waar een actief certificaat aan gekoppeld is.

Afhandelen van notificaties

De Notification objecten die naar je notificatie endpoint worden gepost, zullen altijd thin notificaties zijn. Dit betekent dat ze alleen voldoende informatie bevatten om je te vertellen welke zorgorganisatie-omgeving betrokken is, welk type record op welke manier is gewijzigd en wat de id van dit record is, zie notificatie-model.
Daarom heeft je integratie altijd toegang nodig tot API’s die het ophalen van deze records mogelijk maken op basis van hun ID, zodat je integratie ze kan ophalen, inspecteren en kan bepalen wat te doen.

Technische details en voorbeelden

Webhook endpoint

De Ons API Webhook-service zal Notificatie-objecten POST‘en naar het geconfigureerde notificatie URL. Jouw integratie moet deze requests accepteren en reageren met een 200 statuscode om aan te geven dat de melding is ontvangen. Verzoeken waarbij geen verbinding kan worden gemaakt, of die geen 200-respons binnen 5 seconden ontvangen, worden beschouwd als mislukte verzoeken. We raden aan om requests te accepteren, de melding op te slaan in een soort wachtrij, te reageren met een 200 statuscode en vervolgens de request te verwerken in een ander proces. Dit ontkoppelt het ontvangen en verwerken van gebeurtenissen en voorkomt dat je gebeurtenissen mist wanneer de verwerking tijdelijk vertraagt. Plan om 100’en gebeurtenissen per seconde te ontvangen, aangezien het verkeer kan pieken bij: bulkcorrecties, imports, on-demand bulkheraflevering van mislukte notificaties, of een inhaalslag na downtime.

Authenticatie

  • Onze service zal zichzelf identificeren door middel van een HTTP-header genaamd X-Signature-SHA512. Deze header is een HMAC (Hash-based message authentication code) dat de geconfigureerde secret en payload van de request hashed met het SHA512 algoritme. De secret is te genereren in de pagina van de koppeling.
  • Bij een correcte HMAC verwacht onze service dat er met een 200 statuscode wordt gereageerd. Als de HMAC incorrect is, wordt er verwacht dat er met een 401 statuscode wordt gereageerd. Bij het instellen van je URL’s zal geverifiëerd worden of dit correct is geïmplementeerd door middel van een NOP-event
  • We verwachten dat je server HTTPS gebruikt.

Dit is hoe een HMAC gegenereerd kan worden in Java:

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

public class SignatureGenerator {

    private static final String ALGORITHM = "HmacSHA512";

    public static String generateSignature(String data, String secret) throws NoSuchAlgorithmException, InvalidKeyException {
        Mac mac = Mac.getInstance(ALGORITHM);

        SecretKeySpec secretKeySpec = new SecretKeySpec(secret.getBytes(), ALGORITHM);

        mac.init(secretKeySpec);

        byte[] macBytes = mac.doFinal(data.getBytes());
        
        return toHexString(macBytes);
    }

    private static String toHexString(byte[] bytes) {
        StringBuilder hexString = new StringBuilder();
        for (byte b : bytes) {
            String hex = String.format("%02x", b);
            hexString.append(hex);
        }
        return hexString.toString();
    }

    public static void main(String[] args) {
        try {
            String data = "{\"customerCode\":\"TE1000\",\"modelType\":\"client\",\"eventType\":\"CREATE\",\"id\":1,\"timestamp\":\"2024-08-22T10:08:11+02:00\",\"amountOfRetries\":0}";
            String secret = "SuperSecret";
            String signature = generateSignature(data, secret);
            System.out.println("Signature: " + signature);
        } catch (NoSuchAlgorithmException | InvalidKeyException e) {
            e.printStackTrace();
        }
    }
}

Notificatie-model

De verzonden Notification’s zullen eruit zien als:

{
  "customerCode": "TE1002",
  "modelType": "client",
  "eventType": "CREATE",
  "id": 1234,
  "timestamp": "2024-08-22T10:08:11+02:00", 
  "amountOfRetries": 0
}
  • customerCode zal de zorgorganisatie-omgeving identificeren en dit komt overeen met de customerCode die wordt gebruikt in de certificaten die je gebruikt voor API-verzoeken.
  • modelType zal het model aangeven.
  • eventType het type actie (CREATE, UPDATE, DELETE, CUSTOM, NOP) die het evenement heeft getriggerd.
  • id het id van het model.
  • timestamp wanneer het event is getriggered.
  • amountOfRetries hoevaak dit event geprobeerd is te versturen.

NOP-event

Een NOP-event staat voor “no operation” event. Bij het ontvangen van een NOP-event hoeft er alleen de HMAC gecontroleerd te worden. Op basis van de HMAC moet dan een 200 of 401 statuscode teruggestuurd worden. NOP-events kunnen genegeerd worden (ze worden alleen gebruikt om jouw HMAC-implementatie te valideren)

Ondersteunde events

Beschikbare modelType’s en eventType’s kunnen in de loop van de tijd worden uitgebreid, maar je zult nooit meldingen ontvangen voor gebeurtenissen waarop je je niet hebt geabonneerd. De momenteel ondersteunde events zijn:

CREATE, UPDATE, DELETE Events
EventType ModelType Beschrijving
client CREATE, UPDATE, DELETE Bij het aanmaken, wijzigen of verwijderen van een cliënt.
client_address CREATE, UPDATE, DELETE Bij het aanmaken, wijzigen of verwijderen van een koppeling tussen cliënt en address.
client_contact_relation CREATE, UPDATE, DELETE Bij het aanmaken, wijzigen of verwijderen van een relatie tussen cliënt en contact.
insurance CREATE, UPDATE, DELETE Bij het aanmaken, wijzigen of verwijderen van verzekeringsgegevens.
client_contact_relation_address CREATE, UPDATE, DELETE Bij het aanmaken, wijzigen of verwijderen van een adres van een contact dat een relatie heeft met een cliënt.
location_assignment UPDATE Bij het wijzigen van een koppeling tussen locatie en cliënt.
report CREATE, UPDATE, DELETE Bij het aanmaken, wijzigen of verwijderen van een rapportage.
employee CREATE, UPDATE, DELETE Bij het aanmaken, wijzigen of verwijderen van een medewerker.
hour_type CREATE, UPDATE Bij het aanmaken of wijzigen van uur soorten.
location CREATE, UPDATE, DELETE Bij het aanmaken, wijzigen of verwijderen van een locatie.
team CREATE, UPDATE, DELETE Bij het aanmaken, wijzigen of verwijderen van een team.
user CREATE, UPDATE, DELETE Bij het aanmaken, wijzigen of verwijderen van een gebruiker.
address CREATE, UPDATE, DELETE Bij het aanmaken, wijzigen of verwijderen van een adres.
employee_address CREATE, UPDATE, DELETE Bij het aanmaken, wijzigen of verwijderen van een koppeling tussen medewerker en adres.
expertise_profile CREATE, UPDATE Bij het aanmaken of wijzigen van een deskundigheidsprofiel.
contract CREATE, UPDATE, DELETE Bij het aanmaken, wijzigen of verwijderen van een contract van een medewerker.
care_plan CREATE, UPDATE, DELETE Bij het aanmaken, wijzigen of verwijderen van een zorgplan.
team_assignment CREATE, UPDATE, DELETE Bij het aanmaken, wijzigen of verwijderen van een koppeling tussen medewerker en team .
care_allocation CREATE, UPDATE, DELETE Bij het aanmaken, wijzigen of verwijderen van zorgopnamegegevens van een cliënt.
client_employee_relation CREATE, UPDATE, DELETE Bij het aanmaken, wijzigen of verwijderen van een relatie tussen cliënt en medewerker.
CUSTOM Events

We ondersteunen ook enkele events die niet een CREATE/UPDATE/DELETE van een enkel record zijn maar een bepaalde gebeurtenis vertegenwoordigen. Deze tabel legt uit welke events dat zijn en waar het ID in het event naar verwijst:

EventType ModelType Beschrijving ID verwijst naar
external_care_providers_changed CUSTOM Bij het wijzigen van de zorgverleners van een cliënt Client
client_employee_relations_changed CUSTOM Bij het wijzigen van betrokken medewerkers in het cliëntennetwerk van een cliënt. Client
team_assignment_changed CUSTOM Bij het wijzigen van een team van een medewerker. Employee
care_plan_activated CUSTOM Bij het activeren van een zorgplan van een cliënt. Client
client_careallocations_changed CUSTOM Bij het wijzigen van zorgopnamegegevens van een cliënt. Client

Leveringsvolgorde

We kunnen niet garanderen dat meldingen worden afgeleverd in de volgorde waarin ze worden geactiveerd. Dit betekent dat je bijvoorbeeld een UPDATE-notificatie kunt zien voor een client waarvoor je de CREATE nog niet hebt gezien. Ontwerp je integratie zo dat deze situaties kan afhandelen. Dit kan voorkomen omdat onze webhook-service is geïmplementeerd met meerdere instances die meldingen in batches ophalen, en omdat de levering van een enkele notificaties kan mislukken en de herhaling ervan deze mogelijk na een andere melding voor hetzelfde record plaatst waarvan de levering is gelukt. Bijvoorbeeld:

10:00:00 CREATE CLIENT 1  <- De levering van deze melding mislukt
10:00:05 UPDATE CLIENT 1  <- De levering van deze melding slaagt
10:01:00 CREATE CLIENT 1  <- De heraflevering van de melding slaagt deze keer

Mislukte bezorgpogingen

Requests die niet binnen 5 seconden worden beantwoord met een 200 statuscode worden beschouwd als mislukte requests. Bezorging wordt niet automatisch opnieuw geprobeerd. We slaan events waarvoor de bezorging is mislukt 24 uur lang op en verwijderen ze vervolgens. We kunnen tot 1.000.000 events bewaren, daarna komen de events in een ‘overflow’ en gaan ze verloren. Je integratie kan opnieuw bezorgen van mislukte meldingen aanvragen door een PUT-request met een lege body te sturen naar /webhooks/redeliver. Dit wordt gedaan met een certificaat dat bij een koppeling is geconfigureerd, hiermee kun je per stage (development, staging, production) alle gemiste notificaties van jouw koppeling opnieuw laten afleveren.

Plan voor resynchronisatie

Mislukte bezorgingen van Ons API Webhook-notificaties worden 24 uur lang opgeslagen en kunnen gedurende die periode opnieuw worden geprobeerd. Als je webhook-endpoint langer dan die periode offline is, gaan de gemiste notificaties verloren. We raden je aan een optie voor resynchronisatie te ontwerpen voor het geval dat gebeurt.

Event loops

Als je reageert op een notificatie door het record in Ons bij te werken waarvoor je de notificatie hebt ontvangen, ontvang je een ander event voor datzelfde record. Als dat tweede event een nieuwe update vanuit je integratie activeert, kan dit een event loop veroorzaken. Hieronder staan voorbeelden van twee situaties die een event loop veroorzaken.

Voorbeeld van een event loop in geval van een enkele integratie

Als voorbeeld van hoe dingen mis kunnen gaan, stel dat je een automatische spellingscorrector hebt geïmplementeerd die reageert op notificaties over de creatie of update van een Report en het Report opnieuw opslaat met gecorrigeerde spelling. Wat er kan gebeuren als je het Report opslaat zonder te controleren of er iets is veranderd:

  1. Gebeurtenis ontvangen voor Report 1234
  2. Haal Report 1234 op
  3. Corrigeer spelling
  4. PUT Report 1234 (ongeacht of er iets is veranderd aan het model)
  5. Ga terug naar 1

Je kunt deze lus doorbreken door te detecteren dat je integratie niets heeft veranderd aan het Report en het niet op te slaan.

Voorbeeld van een event loop in geval van een meerdere integraties

Voortbouwend op het bovenstaande voorbeeld. Zelfs als je integratie op de hoogte is van notificaties die zijn gemaakt door zijn eigen acties, kunnen twee integraties elkaar activeren. Stel je twee spellingscontrole-integraties voor, die afzonderlijk geen event loops veroorzaken, met iets andere spellingregels:

  1. Beide integraties ontvangen een CREATE-event voor Report 1234
  2. Beide integraties voeren hun spellingscontrole uit
    1. Integratie A brengt geen wijzigingen aan en werkt het Report niet bij
    2. Integratie B brengt enkele wijzigingen aan en werkt het Report bij
  3. Beide integraties ontvangen een UPDATE-event voor Report 1234
    1. Integratie A brengt wijzigingen aan en werkt het Report bij
    2. Integratie B brengt geen wijzigingen aan en werkt het Report niet bij
  4. Beide integraties ontvangen een UPDATE-event voor Report 1234
    1. Integratie A brengt geen wijzigingen aan en werkt het Report niet bij
    2. Integratie B brengt wijzigingen aan en werkt het Report bij
  5. Terug naar 3

Deze loop is iets moeilijker te doorbreken, aangezien er iets is veranderd sinds de laatste keer dat je integratie het record heeft opgeslagen. We raden aan om een controle te implementeren om ervoor te zorgen dat je niet herhaaldelijk hetzelfde record bewerkt.

Open API specificatie

Jouw webhooks endpoint moet aan deze specificatie voldoen. Je kunt je eigen ‘path’ configureren. Download de specificatie hier.