Skava Skava / Wiki

Conectarea elementelor personalizate pentru dezvoltatori

Această pagină este destinată dezvoltatorilor care conectează backend-ul unei companii la Skava. Crearea și publicarea unui element API sunt descrise în Elemente personalizate: interfețe API; aici acoperim tot ce trebuie să se întâmple la celălalt capăt al liniei.

Ideea într-o singură propoziție: Skava nu cunoaște domeniul dvs. Cunoaște exact un singur format, cardul. Dvs. decideți ce conține, noi verificăm doar forma, dimensiunea și siguranța. O comandă de materiale este un exemplu; următoarea companie colectează feedback-ul utilizatorilor, iar cea de după aceea arhivează o fotografie de șantier în propriile înregistrări.

Fluxul pe scurt

  1. Un administrator de companie creează un element API în Skava: un formular plus adresa, metoda și token-ul backend-ului dvs.
  2. Cineva din chat completează formularul și îl trimite.
  3. Skava apelează backend-ul tău și trimite valorile completate ca JSON.
  4. Răspunsul tău devine cartea din chat.
  5. Opțional, raportezi stări noi ulterior prin callback. Fiecare raport devine o altă carte; cea anterioară rămâne.

Cerințe pentru backend-ul tău

  • HTTPS. Doar https://, fără http, fără credențiale în adresă, maximum 2000 de caractere.
  • Accesibil public. Gazda trebuie să se rezolve exclusiv către IP-uri publice. Localhost, rețele private, link-local și metadatele cloud sunt respinse, iar acest lucru este verificat la fiecare apel.
  • Adresă fixă. Skava rezolvă gazda o singură dată și fixează conexiunea la acel IP. O modificare DNS în timpul apelului nu are efect.
  • Fără redirecționări. Un 301 către adresa „corectă” este considerat o eșec. Introduceți adresa finală imediat.
  • Timp de răspuns. Timpul de așteptare este configurabil per element și limitat rigid la 30 de secunde. Dacă aveți nevoie de mai mult, răspundeți imediat și raportați rezultatul ulterior prin callback.
  • Mărimea răspunsului. Skava citește cel mult 256 KiB.
  • Content-Type. Corpul este analizat doar cu application/json.

Cererea care ajunge la tine

Metoda este GET, POST, PUT sau PATCH, în funcție de element. În cazul POST, PUT și PATCH, valorile ajung ca corp JSON, iar în cazul GET ca parametri de interogare.

Autentificarea este un singur antet, al cărui nume și prefixul valorii sunt configurate în element, de obicei Authorization cu prefixul Bearer . Tokenul este stocat criptat pe partea noastră. Anteturile host, content-length, content-type, cookie și accept-encoding nu pot fi setate.

Corpul este un obiect plat. Cheile sunt alese de cel care a construit elementul; imbricarea apare doar acolo unde au adaugat o tabela sau un selector de produse:

{"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": "…"}

Trei chei vin mereu de la noi, deci nu le folosi singur:

  • locale: codul limbii utilizatorului. Raspunde in acea limba; noi nu traducem textele tale.
  • callback_url si callback_token: callback-ul pentru aceasta interactiune, vezi mai jos. Ele sunt prezente doar cand apelul vine dintr-un chat.

Campurile de context, precum nume, companie, proiect sau subchat, sunt completate de server in sine, derivate din canalul in care a fost rulat elementul. Un client modificat nu poate pretinde un alt nume de proiect acolo.

Răspunsul: formatul cardului

Răspundeți cu 2xx și un obiect card. Acesta este exact ceea ce devine cardul în chat:

{"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 (obligatoriu): numărul întreg 1. Ca text ("1") este respins. Fără acesta, răspunsul nu este considerat un card și se aplică maparea răspunsului configurată în element.
  • title: titlul cardului.
  • state: doar culoarea și tonul pictogramei, una dintre ok, pending, warn, error. O valoare necunoscută revine la ok și primiți un indiciu.
  • status_text: text liber pe care nu îl interpretăm. Se află în partea de sus a cardului și apare și în lista de chat și în notificările push.
  • fields: o listă de label și value. Maximum 20 de intrări, label 80 de caractere, value 200, title și status_text câte 120. Valorile prea lungi sunt scurtate, nu respinse: o comandă nu ar trebui să eșueze din cauza unui detaliu.
  • icon: vezi mai jos.

Ce face Skava cu textele tale înainte să ajungă în chat: pauzele de rând și caracterele de control sunt eliminate (un caracter de la dreapta la stânga ar putea inversa afișarea unei sume), cratimele inversate sunt înlocuite, iar orice începe cu [SKAVA: este neutralizat. Ultima măsură previne ca o valoare din card să fie citită ca un alt element de chat, de exemplu o cerere de plată.

Linkurile în câmpuri, HTML și imaginile nu pot fi setate. Un chat este un mediu de încredere, iar o adresă clicabilă dintr-un backend extern ar fi o invitație de a reconstrui o pagină de autentificare.

Inputurile utilizatorului aparțin serverului: ele apar pe prima card și nu le poți suprascrie. În chat, ele reprezintă înregistrarea a ceea ce a fost efectiv trimis.

Pictograme

Cu icon, cardul primește propria sa marcă în antet. Două variante:

Un nume din setul inclus: 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.

Sau propriul SVG sub formă de șir de caractere. Din acesta, Skava preia doar geometria (path, circle, ellipse, rect, line, polyline, polygon cu atributele lor numerice) și își construiește propria imagine. Scripturile, stilurile, referințele externe, foreignObject și atributele de evenimente sunt eliminate; un doctype sau o entitate duce la respingere; fișierul poate avea cel mult 8 KiB și poate conține cel mult 16 forme. Culoarea, grosimea liniei și dimensiunea sunt stabilite de Skava, astfel încât o pictogramă nu se poate masca ca un control. Lucrați pe o grilă de 24 pe 24.

Fără icon, rămâne marcajul implicit.

Callback: raportarea ulterioară a stărilor

Apelul conține callback_url și callback_token. Folosiți-le pentru a raporta stări noi ulterior:

POST <callback_url> cu Authorization: Bearer <callback_token> și Content-Type: application/json, corp de cel mult 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}

Pe lângă card, există trei valori opționale:

  • seq: contorul propriu. Un raport cu o valoare mai mică sau egală este respins, astfel încât două rapoarte nu se pot depăși reciproc. Fără seq, ultimul raport primit are prioritate.
  • final: închide interacțiunea. Tokenul devine invalid și nu mai apar alte carduri. Este permis și în răspunsul prim, pentru fluxuri fără pași următori.
  • notify: setat la false pentru a publica cardul discret, fără număr de mesaje necitite și fără notificare. Pentru pași intermediari care nu ar trebui să trezească pe nimeni. Fără această setare, cardul este un mesaj perfect normal.

Fiecare raport devine un card separat în chat, iar cel anterior rămâne. Astfel, este clar ce stare a fost raportată. Din acest motiv, recomandarea este: trimite doar ce s-a schimbat. Un card care repetă numărul comenzii, articolele și totalul pentru a patra oară este doar zgomot pentru cititor.

Două limite: același raport de două ori nu produce un al doilea card, iar o interacțiune poate publica cel mult 50 de carduri. O interacțiune acceptă rapoarte timp de 90 de zile.

Răspunsuri la care trebuie să reacționezi

  • 200 cu {"result": "success", "updated": true, "seq": 3, "closed": false, "hints": []}. Citește indiciile: ele indică ce a fost scurtat sau eliminat.
  • 401: token greșit sau id de interacțiune. Nu repeta.
  • 410: interacțiune închisă sau expirată. Nu repeta.
  • 422: card inutilizabil, cu hints ca motiv. Corectează mai întâi.
  • 400 JSON invalid, 413 prea mare, 429 prea multe cereri (reîncearcă cu o pauză), 500 eroare din partea noastră, reîncearcă mai târziu.

Exemplul 1: o comandă cu istoricul stărilor

Pașul 1, cererea către backend-ul tău:

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"}

Pașul 2, răspunsul tău imediat:

{"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"}]}}

Chatul afișează acum o card cu o pictogramă de pachet, starea și datele introduse de utilizator.

Pasul 3, ulterior, la selecție:

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

O a doua card discret, fără câmpuri: s-a schimbat doar starea.

Pasul 4, la expediere:

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}

Acest card poate trezi pe cineva, de aceea nu are notify: false.

Pasul 5, la livrare:

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

Cu final, interacțiunea este închisă și tokenul nu mai funcționează.

Exemplul 2: o acțiune fără pași următori

Nu fiecare flux are o istoric. Un element cu un singur câmp care transmite ceva către sistemul tău are nevoie de o singură răspuns:

{"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 contează aici: altfel, interacțiunea ar rămâne deschisă timp de 90 de zile cu un token valid, deși nu vei mai raporta nimic.

Selector de produse din catalog

După ce compania a încărcat catalogul său de articole, elementul poate conține blocul selector de produse. Utilizatorul compune un coș din acesta, iar tu îl primești ca listă sub cheia aleasă de cel care a construit elementul:

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

Deoarece cheia este liberă, caută prima listă care are această structură, nu un nume fix. Înainte de trimitere, Skava verifică dacă fiecare număr există cu adevărat în catalogul acelei companii, cu un maximum de 50 de articole. În card, articolele apar ca o listă cu imaginea produsului, numele și cantitatea.

Testare

  • Ping în editorul de elemente trimite un HEAD simplu, fără token și fără date. Răspunde cu orice; orice răspuns HTTP contează ca accesibil.
  • Cerere de test declanșează un apel real cu valori de exemplu, chiar dacă elementul este încă în stadiu de schiță, și afișează cererea, răspunsul și mesajele validatorului de card.
  • Previzualizare în fila din apropiere: lipește JSON-ul răspunsului, verifică și vezi cardul finalizat împreună cu indiciile. Verificarea se face pe server cu același cod ca în producție.
  • Server de exemplu: un furnizor de exemplu complet rulează pe api.skava.io și folosește tot ce a fost descris mai sus. Sursa sa se află în depozit, în example_order_server/, aproximativ 600 de linii de bibliotecă standard pură, concepută pentru a fi copiată.

Ce altceva ar trebui să știi

  • Cardul este un mesaj de chat perfect normal. Apare în căutare, poate fi citat și rămâne în istoric.
  • Este trimis de expeditorul sistemului, nu de un cont al companiei tale. Apare totuși pe partea celui care a rulat elementul, iar titlul specifică a cărui sistem scrie.
  • Cine poate executa este setat pe element: doar membrii companiei sau și persoane externe care împărtășesc un chat cu acesta. Când compania ta părăsește chatul, permisiunea se termină automat.
  • Un element API cu un token expirat este inactiv: aplicațiile actuale îl ascund din meniu, iar un apel trimis totuși este respins pe server. Un administrator stochează un token nou pentru acesta, ceea ce funcționează și pe o interfață publicată.

Conexe

Creare și publicare: Elemente personalizate: interfețe API. Documente completabile în loc de interfețe: Elemente personalizate: documente.