Vigilae Connect

Un API pe care îl puteți citi înainte să semnați.

Specificația este publică, semnătura webhook-urilor se poate verifica în zece linii la dumneavoastră. Această pagină documentează ce expune API-ul astăzi — nimic mai mult, și asta în mod deliberat: ce nu este livrat nu este documentat.

  • Specificație OpenAPI lizibilă fără cheie și fără cont
  • Niciodată un raport de tranzacție suspectă, niciodată verbatim de client
  • Webhook-uri semnate, verificabile în afara Vigilae

Servită chiar de API: contractul pe care îl citiți este cel care rulează.

Perimetrul

Tot parcursul dosarului și două excluderi care nu se vor clinti.

Software-ul dumneavoastră poate duce un dosar de la cap la coadă: crearea clientului, deschiderea dosarului, depunerea documentelor, lansarea screeningului, declararea beneficiarilor reali, citirea cotării riscului și preluarea dosarului de probe. Două lucruri nu vor trece niciodată pe acolo, iar aceasta nu este o limitare de abonament: niciun raport de tranzacție suspectă și nicio redare textuală a spuselor clientului dumneavoastră. Primul este un act pe care legea îl rezervă persoanei care raportează; a doua nu are ce căuta într-un canal de integrare.

Dosarul, de la cap la coadă

Clienți, dosare, documente justificative, screening, beneficiari reali, cotarea riscului, dosar de probe, control de integritate. Fiecare resursă își are permisiunea ei: cheia dumneavoastră nu deschide decât ceea ce i-ați dat.

Jurnal și indicatori agregați

Evenimentele pKYC ale cabinetului — document expirat, schimbare de beneficiar real, re-screening de tratat — și contoare de portofoliu pentru tabloul dumneavoastră de bord. Răspuns întotdeauna mărginit, cursor stabil.

Ce scrieți poartă un nume

Depunere, screening, calificare: fiecare scriere își cere permisiunea și consemnează operatorul. O calificare anonimă este refuzată — integrarea consemnează o decizie umană, nu produce niciuna.

API-ul este gândit server-to-server: o cheie în cod livrat browserului este o cheie publicată. Lăsați un proxy pe server să țină cheia, niciodată pagina.

Chei

Chei cu acces delimitat, afișate o singură dată, revocabile imediat.

  • Format. Fiecare cheie începe cu vgk_ și se trimite ca Authorization: Bearer vgk_…. Secretul este afișat doar la creare: nu păstrăm decât amprenta sa SHA-256.
  • Scope-uri. O cheie poartă doar scope-urile bifate la crearea ei: cele generale lecture (citire, implicit) și ecriture (scriere) sau scope-uri fine, resursă cu resursă — clients:, dossiers:, pieces:, criblage: (în lecture sau ecriture), origine-fonds:lecture, journal:lecture.
    Moștenirea urmează sufixul și merge într-un singur sens: lecture acoperă orice *:lecture, ecriture orice *:ecriture; un scope fin nu deschide nimic dincolo de el însuși.
    Șase scope-uri ies din această pereche și, prin urmare, nu se moștenesc din nicio cheie generală: alertes:qualifier, embed:emettre, adversemedia:consulter, conformite:consulter, dispositif:consulter, integrite:consulter. Fiecare se deleagă separat, la crearea cheii.
    O cheie fără scope-ul necesar primește un 403 — vedeți #scopes.
  • Expirare. La un an de la creare (vizibilă în consola cabinetului). O cheie expirată primește un 401 explicit — vedeți #cle-expiree.
    O cheie poate înceta să fie acceptată și înainte de această dată, atunci când API-ul nu mai face parte din abonamentul cabinetului. Oprirea intervine atunci la cel puțin 30 de zile după un prim e-mail către cabinet, la data indicată de un al doilea e-mail, trimis cu cel puțin 7 zile înainte. Odată stabilită, această dată se poate citi în consola cabinetului (câmpul coupure_le din GET /connect/cles), iar fiecare răspuns la un apel acceptat o anunță în antetul Sunset până când sosește. După această dată, apelul primește 401-ul descris la #authentification, cu "motif": "fin_option_api"; dacă API-ul revine în abonament, cheia este din nou acceptată, până la propria ei dată de expirare.
    O cheie revocată nu revine odată cu API-ul. Iar când întregul abonament este suspendat sau se încheie, cheile încetează pe loc să fie acceptate, fără acest termen.
  • Debit. 60 de cereri/minut per cheie (ajustabil per cheie). Un 429 poartă Retry-After și antetele X-RateLimit-Limit / -Remaining / -Reset.
  • Revocare. Imediată, din consolă. Rezolvarea se face prin amprentă: cheile nu pot fi enumerate.
Pornire rapidă

Trei apeluri curl și ați văzut tot.

# Stare de funcționare + autentificarea cheii curl -s https://vigilae.org/api/v1/sante \ -H "Authorization: Bearer vgk_cheia_dumneavoastra" # Jurnalul de monitorizare, de la început, în pagini de câte 100 curl -s "https://vigilae.org/api/v1/evenements?depuisSeq=0&limite=100" \ -H "Authorization: Bearer vgk_cheia_dumneavoastra" # Calificați evenimentul 42 (scope de scriere) curl -s -X POST https://vigilae.org/api/v1/evenements/42/qualifier \ -H "Authorization: Bearer vgk_cheia_dumneavoastra" \ -H "Content-Type: application/json" \ -d '{"statut":"qualifie","disposition":"traite"}'

Paginarea, într-o singură regulă

Transmiteți depuisSeq (0 la primul apel) și limite (plafonată la 500): răspunsul este sortat după seq crescător și returnează prochainSeq, de retransmis ca atare la apelul următor. O pagină mai scurtă decât limite înseamnă sfârșitul jurnalului — prochainSeq rămâne atunci stabil și servește drept cursor de interogare periodică. Fără depuisSeq, obțineți vederea „cele mai recente întâi”, plafonată la 500.

Portofoliul se interoghează pe /api/v1/portefeuille/agregats — contoare, un singur răspuns, fără paginare.

Webhook-uri

Semnate, cu marcaj temporal, livrate cel puțin o dată.

În loc să interogați jurnalul, primiți-l: Vigilae livrează evenimentele la URL-ul dumneavoastră, în ordine, în loturi de cel mult 100. Livrarea este at-least-once — cursorul avansează doar la 2xx-ul dumneavoastră, lot cu lot — iar idempotența se face după seq: procesați fiecare secvență exact o dată (#idempotence).

Verificarea semnăturii

Fiecare livrare poartă antetul x-vigilae-signature: t=<unix>,v1=HMAC-SHA256(secret, t + "." + body). Recalculați v1 din corpul brut primit și respingeți orice marcaj temporal t mai vechi de 5 min: acesta este mecanismul anti-replay. În timpul unei rotații de secret, antetul poartă câte un v1 pentru fiecare secret încă valid (suprapunere de 24 h): acceptați dacă oricare dintre ele se potrivește.

// Node — verificarea semnăturii (fără dependențe) import { createHmac, timingSafeEqual } from 'node:crypto'; export function signatureValid(header, rawBody, secrets, toleranceMs = 5 * 60 * 1000) { const t = Number((/(?:^|,)t=(\d+)/.exec(header) || [])[1]); if (!t || Math.abs(Date.now() - t * 1000) > toleranceMs) return false; // anti-replay const received = [...header.matchAll(/v1=([0-9a-f]{64})/g)].map((m) => m[1]); return [].concat(secrets).some((secret) => { const expected = createHmac('sha256', secret).update(t + '.' + rawBody).digest('hex'); return received.some((r) => r.length === expected.length && timingSafeEqual(Buffer.from(r), Buffer.from(expected))); }); }
# Python — aceeași verificare import hmac, hashlib, re, time def signature_valid(header: str, raw_body: bytes, secrets, tolerance_s: int = 300) -> bool: m = re.search(r"(?:^|,)t=(\d+)", header) if not m or abs(time.time() - int(m.group(1))) > tolerance_s: return False # anti-replay received = re.findall(r"v1=([0-9a-f]{64})", header) for secret in secrets: expected = hmac.new(secret.encode(), m.group(1).encode() + b"." + raw_body, hashlib.sha256).hexdigest() if any(hmac.compare_digest(expected, r) for r in received): return True return False

Tranzitoriu: vechiul format sha256=HMAC(body) este încă emis pe x-vigilae-signature-legacy pentru receptoarele deja instalate; eliminarea sa este planificată odată cu webhook-urile v2. Receptoarele noi verifică schema cu marcaj temporal de mai sus, nu pe cea veche.

Rotația se declanșează din consolă (POST /connect/webhook/rotation pe partea aplicației): timp de 24 h vechiul secret încă semnează — răgaz să instalați noul secret la dumneavoastră, fără fereastră de eșec.

Widgeturi încorporate

Starea de vigilență, în ecranele dumneavoastră.

Software-ul dumneavoastră creează deja dosarele prin API; widgeturile îi dau suprafața care lipsea: arătarea stării de vigilență a unui dosar în fișa dumneavoastră de client, fără să reconstruiți o interfață de conformitate. Fluxul ține în trei pași — serverul dumneavoastră emite un token de scurtă durată, URL-ul returnat intră într-un iframe, widgetul afișează. Nu face decât să afișeze: nicio decizie, nicio calificare, nicio scriere nu trece vreodată printr-un widget. Un clic deschide aplicația Vigilae, unde acționează o persoană identificată.

1. Emiteți tokenul — pe server, niciodată în pagină

Cheia vgk_ nu atinge niciodată browserul. Serverul dumneavoastră apelează mintul cu scope-ul dedicat embed:emettre (bifat la crearea cheii, niciodată moștenit), iar spre pagină coboară doar tokenul scurt: cincisprezece minute în mod implicit, plafonat la 5-60, legat de un dosar, o componentă, o origine declarată. Călătorește în fragmentul URL-ului — nu ajunge nici la jurnalele noastre, nici la ale dumneavoastră.

# Un token pentru Compliance Button, eticheta aleasă din catalog curl -s -X POST https://vigilae.org/api/v1/embed/jetons \ -H "Authorization: Bearer vgk_your_key" \ -H "Content-Type: application/json" \ -d '{"dossier_id":"D123","composant":"bouton", "audience":"https://your-software.example","libelle":"controler_client"}' # 201 -> { "jeton": "…", "expire_le": "…", # "url": "https://vigilae.org/embarque/bouton?c=…#…" }

2. Plasați iframe-ul — lansatorul, în zece linii

Lansatorul vigilae-embed.js creează iframe-ul sandboxat, face handshake-ul și urmărește dimensiunea widgetului (plafonată — iframe-ul nu își impune niciodată înălțimea paginii dumneavoastră). La nivel de CSP, pagina dumneavoastră deschide o singură directivă: frame-src https://vigilae.org. Niciun script inline necesar, nicio dependență. Un iframe scris manual funcționează la fel de bine.

<script src="https://vigilae.org/embarque/vigilae-embed.js" defer></script> <div id="vigilance"></div>
// În scriptul dumneavoastră: url-ul vine de la SERVERUL dumneavoastră, care a apelat mintul var widget = VigilaeEmbed.monter({ conteneur: 'vigilance', url: urlReturnedByTheMint, renouvelerJeton: function () { // la expirare: reemiteți pe server return fetch('/my-server/vigilae-token').then(function (r) { return r.text(); }); }, }); // widget.rafraichir(token) trimite un token nou; widget.demonter() elimină totul.

3. Compliance Button: eticheta dumneavoastră, starea noastră

Eticheta butonului se alege dintr-un catalog închis de etichete — niciodată text liber pe o suprafață care vorbește despre vigilență. Shell-ul încorporat le afișează însă doar în franceză sau engleză (parametrul ?lang= din URL-ul widgetului, cu repliere pe franceză), nu încă în limba dumneavoastră; lista de mai jos vă dă sensul lor:

  • controler_client — „Verificați acest client” (implicit)
  • lancer_vigilance — „Lansați vigilența”
  • verifier_be — „Verificați beneficiarii reali”
  • preparer_dossier — „Pregătiți dosarul LCB-FT”

Pastila de status, în schimb, redă o stare calculată de Vigilae: a_jour (verde — verificare în liste și cotare la zi), a_revoir (portocaliu — verificare în liste sau cotare expirate, sau sursa a eșuat la ultima trecere), alerte (roșu — cel puțin o alertă de tratat), inconnu (gri — dosar niciodată verificat în liste). Eticheta se configurează, semantica niciodată: culoarea este legată de stare chiar în shell, care ignoră orice încercare de a o suprascrie prin postMessage. Un dosar în alertă se afișează în alertă, indiferent de stilizare.

Contractul postMessage, în întregime

Widgetul emite vigilae:pret, vigilae:taille (auto-ajustare), vigilae:expire (reemiteți pe server, apoi postați vigilae:jeton) și vigilae:ouvrir. Niciodată un nume, un risc sau o alertă în interiorul unui mesaj: software-ul dumneavoastră are deja totul prin API-ul server-to-server, și acest canal nu va deveni un al doilea.

Declararea originilor: de către administratorul cabinetului. Un token de embed este legat de o origine declarată a cabinetului dumneavoastră — ea este cea care pilotează CSP-ul frame-ancestors al shell-ului. Administratorul o declară direct în Vigilae, pe ecranul „Integrări și securitate”: cel mult zece origini https://, gazdă explicită, niciodată un metacaracter; componentele pe care le activează; și o revocare în masă care ucide dintr-un gest toate tokenurile deja emise. http://localhost este admis doar pe un cabinet de probă — scrieți la contact@vigilae.org (subiect „Embedded widgets”) pentru a deschide unul pe durata integrării dumneavoastră. Nicio origine declarată: mintul refuză cu un 400. O instanță al cărei stocare de origini nu este conectată: un 501 explicit — vedeți #embed-indisponible.
Mediu de test

Sandbox: la cerere.

Nu există încă un sandbox self-service — preferăm să v-o spunem aici decât să o descoperiți singuri. Scrieți la contact@vigilae.org (subiect „Acces API”): deschidem un cabinet de probă cu date fictive pe durata integrării dumneavoastră și rămânem disponibili cât timp aceasta avansează.

Fiecare clasă de erori API are o adresă stabilă în referința erorilor: #authentification, #scopes, #cloisonnement, #debit, #signature… Răspunsurile de eroare ale API-ului vor trimite către aceste ancore.

API-ul nu expune nici rapoarte de tranzacție suspectă, nici verbatim de client, prin construcție (art. L.561-18 din CMF francez). Nicio decizie de vigilență nu este luată de API: acesta expune și califică evenimente; profesionistul decide.