Skava Skava / Wiki

Custom Elements voor ontwikkelaars

Deze pagina is bedoeld voor ontwikkelaars die de backend van een bedrijf aan Skava koppelen. Het maken en publiceren van een API-element staat beschreven op Custom Elements: API-interfaces; hier behandelen we alles wat aan de andere kant van de lijn moet gebeuren.

Het idee in één zin: Skava kent uw domein niet. Het kent precies één formaat, de kaart. U bepaalt wat erop staat, wij controleren alleen vorm, afmetingen en veiligheid. Een materiaalaanvraag is één voorbeeld; het volgende bedrijf verzamelt gebruikersfeedback, het daaropvolgende archifeert een foto van de bouwplaats in zijn eigen dossiers.

Het proces in grote lijnen

  1. Een beheerder van het bedrijf maakt een API-element aan in Skava: een formulier plus het adres, de methode en de token van uw backend.
  2. Iemand in de chat vult het formulier in en stuurt het door.
  3. Skava roept je backend aan en stuurt de ingevulde waarden als JSON.
  4. Je antwoord wordt de kaart in de chat.
  5. Optioneel rapporteer je later nieuwe statussen via de callback. Elk rapport wordt een nieuwe kaart; de vorige blijft staan.

Eisen voor je backend

  • HTTPS. Alleen https://, geen http, geen inloggegevens in het adres, maximaal 2000 tekens.
  • Openbaar bereikbaar. De host moet uitsluitend naar openbare IP-adressen oplossen. Localhost, privé-netwerken, link-local en cloud-metadata worden afgewezen, en dit wordt bij elke aanroep gecontroleerd.
  • Vast adres. Skava lost de host één keer op en kiest het IP-adres voor de verbinding. Een DNS-wijziging tijdens de aanroep heeft geen effect.
  • Geen doorverwijzingen. Een 301 naar het "juiste" adres telt als mislukking. Voer direct het eindadres in.
  • Reactietijd. De time-out is per element instelbaar en maximaal 30 seconden. Als je langer nodig hebt, reageer dan direct en meld het resultaat later via de callback.
  • Responsgrootte. Skava leest maximaal 256 KiB.
  • Content-Type. De body wordt alleen geparseerd met application/json.

De aanvraag die bij u aankomt

De methode is GET, POST, PUT of PATCH, afhankelijk van het element. Bij POST, PUT en PATCH komen de waarden binnen als JSON-body, bij GET als queryparameters.

Authenticatie is één header waarvan de naam en het voorvoegsel van de waarde in het element zijn geconfigureerd, meestal Authorization met het voorvoegsel Bearer . De token wordt versleuteld opgeslagen aan onze kant. De headers host, content-length, content-type, cookie en accept-encoding kunnen niet worden ingesteld.

De body is een platte object. De sleutels worden gekozen door wie het element heeft gebouwd; geneste structuur verschijnt alleen waar zij een tabel of een productkeuze hebben toegevoegd:

{"artikelnummer": "5100110", "menge": 20, "note": "Please deliver in the morning", "orderer": "Jonas Berger", "company": "Sanitar Berger GmbH", "project": "Spitalstrasse 11", "locale": "de", "callback_url": "https://chat.skava.io/api/v1/custom-elements/interactions/…", "callback_token": "…"}

Drie sleutels komen altijd van ons, dus gebruik ze zelf niet:

  • locale: de taalcodes van de gebruiker. Antwoord in die taal; wij vertalen je teksten niet.
  • callback_url en callback_token: de callback voor deze ene interactie, zie hieronder. Ze zijn alleen aanwezig als de oproep uit een chat komt.

Contextvelden zoals naam, bedrijf, project of subchat worden door de server zelf ingevuld, afgeleid van het kanaal waarin het element is uitgevoerd. Een aangepaste client kan daar geen ander projectnaam claimen.

De respons: het kaartformaat

Antwoord met 2xx en een card-object. Dat is precies wat de kaart in de chat wordt:

{"card": {"v": 1, "title": "Order BST-10001", "state": "pending", "status_text": "Order received", "icon": "package", "fields": [{"label": "Order number", "value": "BST-10001"}, {"label": "Expected", "value": "14/08/2026"}]}}

  • v (verplicht): het gehele getal 1. Als tekst ("1") wordt het afgewezen. Zonder dit veld telt het antwoord niet als kaart en wordt de in het element geconfigureerde responsmapping toegepast.
  • title: de kop van de kaart.
  • state: alleen kleur en ictone, een van ok, pending, warn, error. Een onbekende waarde valt terug op ok en je krijgt een hint.
  • status_text: vrije tekst die we niet interpreteren. Deze staat bovenaan de kaart en wordt ook weergegeven in de chatlijst en in pushmeldingen.
  • fields: een lijst met label en value. Maximaal 20 items, label 80 tekens, value 200, title en status_text elk 120. Waarden die te lang zijn, worden ingekort, niet afgewezen: een order mag niet mislukken om een detail.
  • icon: zie hieronder.

Wat Skava doet met je teksten voordat ze de chat bereiken: regeleinden en controletekens worden verwijderd (een rechts-naar-links teken zou anders de weergave van een bedrag kunnen omkeren), backticks worden vervangen en alles wat begint met [SKAVA: wordt geneutraliseerd. Het laatste punt voorkomt dat een kaartwaarde wordt gelezen als een ander chat-element, bijvoorbeeld een betalingsverzoek.

Links in velden, HTML en afbeeldingen kunnen niet worden ingesteld. Een chat is een vertrouwde omgeving, en een klikbaar adres van een externe backend zou een uitnodiging zijn om een inlogpagina opnieuw te bouwen.

De invoer van de gebruiker hoort bij de server: ze verschijnen op de eerste kaart en je kunt ze niet overschrijven. In de chat vormen ze het bewijs van wat daadwerkelijk is ingediend.

Iconen

Met icon krijgt de kaart een eigen markering in de kop. Twee manieren:

Een naam uit de meegeleverde set: package, package-check, package-open, box, boxes, truck, forklift, warehouse, settings, cog, gauge, wrench, hammer, drill, hard-hat, ruler, paint-roller, construction, clipboard-check, receipt, file-text, camera, clock, calendar-clock, circle-check, circle-alert, triangle-alert, send, mail-check, shopping-cart, credit-card, map-pin.

Of je eigen SVG als tekenreeks. Skava neemt hieruit alleen de geometrie over (path, circle, ellipse, rect, line, polyline, polygon met hun numerieke attributen) en bouwt er zelf een afbeelding van. Scripts, stijlen, externe referenties, foreignObject en event-attributen worden verworpen; een doctype of een entiteit leidt tot afwijzing; het bestand mag maximaal 8 KiB groot zijn en maximaal 16 vormen bevatten. Kleur, lijndikte en grootte worden door Skava ingesteld, zodat een icoon zich niet als een bedieningselement kan voordoen. Werk met een raster van 24 bij 24.

Zonder icon blijft de standaardmarkering behouden.

De callback: latere statussen rapporteren

De aanroep bevat callback_url en callback_token. Gebruik deze om later nieuwe statussen te rapporteren:

POST <callback_url> met Authorization: Bearer <callback_token> en Content-Type: application/json, body maximaal 32 KiB:

{"card": {"v": 1, "title": "Order BST-10001", "state": "pending", "status_text": "Shipped", "icon": "truck", "fields": [{"label": "Tracking number", "value": "DPD123456789"}]}, "seq": 3, "final": false}

Naast de kaart zijn er drie optionele waarden:

  • seq: jouw eigen teller. Een rapport met een kleinere of gelijke waarde wordt genegeerd, zodat twee rapporten elkaar niet kunnen inhalen. Zonder seq wint de laatst aangekomen.
  • final: sluit de interactie af. Het token wordt ongeldig en er verschijnen geen verdere kaarten meer. Ook toegestaan in het eerste antwoord, voor flows zonder vervolg.
  • notify: stel in op false om de kaart stil te posten, zonder ongelezen-teller en zonder melding. Voor tussenschappen die niemand moeten wakker maken. Zonder deze instelling is de kaart een volwaardig bericht.

Elk rapport wordt een eigen kaart in de chat, de vorige blijft staan. Zo is leesbaar welke status is gemeld. Hieruit volgt een aanbeveling: stuur alleen wat veranderd is. Een kaart die voor de vierde keer ordernummer, artikelen en totaal herhaalt, is puur ruis voor de lezer.

Twee limieten: hetzelfde rapport twee keer geeft geen tweede kaart, en een interactie mag maximaal 50 kaarten posten. Een interactie accepteert rapporten gedurende 90 dagen.

Antwoorden waarnaar je moet reageren

  • 200 met {"result": "success", "updated": true, "seq": 3, "closed": false, "hints": []}. Lees de hints: ze geven aan wat is ingekort of weggelaten.
  • 401: verkeerde token of interactie-id. Probeer het niet opnieuw.
  • 410: interactie gesloten of verlopen. Probeer het niet opnieuw.
  • 422: kaart onbruikbaar, met hints als reden. Los dit eerst op.
  • 400 beschadigde JSON, 413 te groot, 429 te veel verzoeken (opnieuw proberen met back-off), 500 onze fout, later opnieuw proberen.

Voorbeeld 1: een bestelling met een statusgeschiedenis

Stap 1, het verzoek naar uw backend:

POST https://api.example.com/v1/orders
Authorization: Bearer <your token>
{"artikelnummer": "5100110", "menge": 20, "orderer": "Jonas Berger", "company": "Sanitar Berger GmbH", "locale": "de", "callback_url": "https://chat.skava.io/api/v1/custom-elements/interactions/1111…", "callback_token": "secret"}

Stap 2, uw directe reactie:

{"card": {"v": 1, "title": "Order BST-10001", "state": "pending", "status_text": "Order received", "icon": "package", "fields": [{"label": "Order number", "value": "BST-10001"}, {"label": "Expected", "value": "14/08/2026"}]}}

De chat toont nu een kaart met een pakketicoon, de status en de invoer van de gebruiker.

Stap 3, later tijdens het selecteren:

POST <callback_url> to {"card": {"v": 1, "title": "Order BST-10001", "state": "pending", "status_text": "Being picked", "icon": "cog", "fields": []}, "seq": 2, "notify": false}

Een rustige tweede kaart zonder velden: alleen de status is gewijzigd.

Stap 4, bij verzending:

POST <callback_url> to {"card": {"v": 1, "title": "Order BST-10001", "state": "pending", "status_text": "Shipped", "icon": "truck", "fields": [{"label": "Tracking number", "value": "DPD123456789"}, {"label": "Carrier", "value": "DPD"}]}, "seq": 3}

Deze kaart kan iemand wakker maken, dus geen notify: false.

Stap 5, bij levering:

POST <callback_url> to {"card": {"v": 1, "title": "Order BST-10001", "state": "ok", "status_text": "Delivered", "icon": "package-check", "fields": []}, "seq": 4, "final": true}

Met final is de interactie afgerond en werkt de token niet meer.

Voorbeeld 2: een actie zonder vervolg

Niet elke flow heeft een geschiedenis. Een element met één veld dat iets doorgeeft aan je systeem heeft maar één antwoord nodig:

{"card": {"v": 1, "title": "Filed", "state": "ok", "status_text": "Stored under project 4711", "icon": "clipboard-check", "fields": [{"label": "Case", "value": "4711"}]}, "final": true}

final: true is hier belangrijk: anders blijft de interactie 90 dagen open met een geldige token, hoewel je nooit meer iets rapporteert.

Productkeuze uit de catalogus

Zodra het bedrijf zijn artikelcatalogus heeft geüpload, kan het element de productkeuze-blok bevatten. De gebruiker stelt een winkelwagen samen en jij ontvangt deze als een lijst onder de sleutel die de maker van het element heeft gekozen:

{"items": [{"artikelnummer": "5100110", "menge": 20}, {"artikelnummer": "5100111", "menge": 2}], "note": "…"}

Omdat de sleutel vrij is, zoek naar de eerste lijst met deze structuur in plaats van naar een vaste naam. Voor het verzenden controleert Skava of elk nummer daadwerkelijk in de catalogus van dat bedrijf bestaat, met maximaal 50 items. In de kaart verschijnen de items als een lijst met productafbeelding, naam en hoeveelheid.

Testen

  • Ping in de elementeditor stuurt een kale HEAD zonder token en zonder data. Antwoord met wat dan ook; elke HTTP-reactie telt als bereikbaar.
  • Testverzoek voert een echte aanroep uit met voorbeeldwaarden, ook als het element nog een concept is, en toont het verzoek, de reactie en de berichten van de kaartvalidator.
  • Voorbeeld in het tabblad ernaast: plak je antwoord-JSON, controleer het en je ziet de afgeronde kaart plus de hints. Het wordt op de server gecontroleerd met dezelfde code als in productie.
  • Voorbeeldserver: een complete voorbeeldleverancier draait op api.skava.io en gebruikt alles wat hierboven is beschreven. De broncode staat in de repository onder example_order_server/, ongeveer 600 regels pure standaardbibliotheek, bedoeld om te kopiëren.

Wat je nog meer moet weten

  • De kaart is een volledig normale chatbericht. Hij verschijnt in de zoekfunctie, kan worden geciteerd en blijft in de geschiedenis staan.
  • Hij wordt verzonden door de systeemafzender, niet door een account van je bedrijf. Hij verschijnt nog steeds aan de kant van degene die het element heeft uitgevoerd, en in de titel staat vermeld welk systeem schrijft.
  • Wie het mag uitvoeren, staat op het element: alleen leden van het bedrijf, of ook buitenstaanders die een chat met het element delen. Als uw bedrijf de chat verlaat, eindigt de machtiging vanzelf.
  • Een API-element met een verlopen token is inactief: actuele apps verbergen het in het menu en een alsnog verzonden oproep wordt serverzijde afgewezen. Een beheerder slaat een nieuw token op, wat ook werkt op een vrijgegeven interface.

Gerelateerd

Aanmaken en vrijgeven: Custom Elements: API-interfaces. Invulbare documenten in plaats van interfaces: Custom Elements: Documenten.