Vigilae Connect

API, które można przeczytać przed podpisaniem.

Specyfikacja jest publiczna, a podpis webhooka można zweryfikować w dziesięciu linijkach po swojej stronie. Ta strona dokumentuje to, co API udostępnia dziś — nic więcej, i to celowo: czego nie wdrożono, tego nie dokumentujemy.

  • Specyfikacja OpenAPI czytelna bez klucza i bez konta
  • Nigdy zgłoszenie podejrzanej transakcji, nigdy dosłowne treści klienta
  • Podpisane webhooki, weryfikowalne poza Vigilae

Serwowana przez samo API: kontrakt, który czytasz, to ten, który działa.

Zakres

Cała ścieżka i dwa wyłączenia, które nie ulegną zmianie.

Twoje oprogramowanie może poprowadzić sprawę od początku do końca: utworzyć klienta, otworzyć sprawę, przesłać dokumenty, uruchomić weryfikację sankcyjną, zgłosić beneficjentów rzeczywistych, odczytać ocenę ryzyka i pobrać dossier dowodowe. Dwie rzeczy nigdy tędy nie przejdą, i nie jest to ograniczenie planu: żadnego zgłoszenia podejrzanej transakcji i żadnych dosłownych treści Twojego klienta. Pierwsze to czynność, którą ustawa zastrzega dla osoby dokonującej zgłoszenia; drugie nie ma czego szukać w kanale integracyjnym.

Sprawa od początku do końca

Klienci, sprawy, dokumenty potwierdzające, weryfikacja sankcyjna, beneficjenci rzeczywiści, ocena ryzyka, dossier dowodowe, kontrola integralności. Każdy zasób ma własne uprawnienie: Twój klucz otwiera wyłącznie to, co mu przyznano.

Dziennik i agregaty

Zdarzenia pKYC kancelarii — wygasły dokument, zmiana beneficjenta rzeczywistego, ponowna weryfikacja do obsługi — oraz liczniki portfela na Twój pulpit. Odpowiedź zawsze ograniczona, kursor stabilny.

To, co zapisujesz, ma swojego autora

Przesłać dokument, uruchomić weryfikację, zakwalifikować: każdy zapis wymaga własnego uprawnienia i odnotowuje operatora. Anonimowa kwalifikacja jest odrzucana — integracja rejestruje decyzję człowieka, sama żadnej nie podejmuje.

API jest zaprojektowane server-to-server: klucz w kodzie wysłanym do przeglądarki to klucz opublikowany. Klucz niech trzyma proxy po stronie serwera, nigdy strona.

Klucze

Klucze o ograniczonych uprawnieniach, pokazywane raz, odwoływalne natychmiast.

  • Format. Każdy klucz zaczyna się od vgk_ i jest przesyłany jako Authorization: Bearer vgk_…. Sekret jest pokazywany wyłącznie przy utworzeniu: przechowujemy jedynie jego skrót SHA-256.
  • Uprawnienia (scopes). Klucz niesie wyłącznie uprawnienia zaznaczone przy jego tworzeniu: ogólne lecture (odczyt, domyślne) i ecriture (zapis) albo drobne, zasób po zasobie — clients:, dossiers:, pieces:, criblage: (w lecture lub ecriture), origine-fonds:lecture, journal:lecture.
    Dziedziczenie idzie po przyrostku i tylko w jedną stronę: lecture pokrywa każde *:lecture, ecriture każde *:ecriture; drobne uprawnienie nie otwiera niczego poza sobą.
    Sześć uprawnień wypada poza tę parę i dlatego nie dziedziczy się z żadnego klucza ogólnego: alertes:qualifier, embed:emettre, adversemedia:consulter, conformite:consulter, dispositif:consulter, integrite:consulter. Każde deleguje się osobno, przy tworzeniu klucza.
    Klucz bez wymaganego uprawnienia otrzymuje 403 — zob. #scopes.
  • Ważność. Rok od utworzenia (data widoczna w konsoli kancelarii). Wygasły klucz otrzymuje jednoznaczne 401 — zob. #cle-expiree.
    Klucz może też przestać być akceptowany przed tą datą, gdy API nie wchodzi już w zakres abonamentu kancelarii. Zatrzymanie następuje wtedy co najmniej 30 dni po pierwszym e-mailu do kancelarii, w dniu podanym w drugim e-mailu, wysłanym co najmniej 7 dni wcześniej. Gdy tylko zostanie ustalona, ta data jest widoczna w konsoli kancelarii (pole coupure_le w GET /connect/cles), a każda odpowiedź na zaakceptowane wywołanie zapowiada ją w nagłówku Sunset, dopóki nie nadejdzie. Po tej dacie wywołanie otrzymuje 401 opisany w #authentification, z "motif": "fin_option_api"; jeśli API wróci do abonamentu, klucz znów jest akceptowany, aż do upływu jego własnego terminu ważności.
    Odwołany klucz nie wraca wraz z API. A gdy cały abonament zostanie zawieszony lub się zakończy, klucze natychmiast przestają być akceptowane, bez zachowania tego terminu.
  • Limit żądań. 60 żądań na minutę na klucz (możliwy do zmiany per klucz). Odpowiedź 429 niesie Retry-After oraz nagłówki X-RateLimit-Limit / -Remaining / -Reset.
  • Odwołanie. Natychmiastowe, z konsoli. Rozpoznawanie odbywa się po skrócie: kluczy nie da się enumerować.
Szybki start

Trzy wywołania curl i masz obraz całości.

# Stan usługi + uwierzytelnienie kluczem curl -s https://vigilae.org/api/v1/sante \ -H "Authorization: Bearer vgk_your_key" # Dziennik monitoringu, od początku, stronami po 100 curl -s "https://vigilae.org/api/v1/evenements?depuisSeq=0&limite=100" \ -H "Authorization: Bearer vgk_your_key" # Kwalifikacja zdarzenia 42 (uprawnienie zapisu) curl -s -X POST https://vigilae.org/api/v1/evenements/42/qualifier \ -H "Authorization: Bearer vgk_your_key" \ -H "Content-Type: application/json" \ -d '{"statut":"qualifie","disposition":"traite"}'

Paginacja w jednej regule

Przekaż depuisSeq (0 przy pierwszym wywołaniu) i limite (maksymalnie 500): odpowiedź jest posortowana rosnąco po seq i zwraca prochainSeq, do przekazania bez zmian w kolejnym wywołaniu. Strona krótsza niż limite oznacza koniec dziennika — prochainSeq pozostaje wtedy stabilny i służy jako kursor odpytywania. Bez depuisSeq otrzymujesz widok „najnowsze najpierw”, ograniczony do 500.

Portfel odpytuje się na /api/v1/portefeuille/agregats — liczniki, jedna odpowiedź, bez paginacji.

Webhooki

Podpisane, ze znacznikiem czasu, dostarczane co najmniej raz.

Zamiast odpytywać dziennik, odbieraj go: Vigilae dostarcza zdarzenia na Twój URL, po kolei, w partiach po maksymalnie 100. Dostarczanie działa w trybie at-least-once — kursor przesuwa się tylko po Twoim 2xx, partia po partii — a idempotencja opiera się na seq: przetwórz każdą sekwencję dokładnie raz (#idempotence).

Weryfikacja podpisu

Każda dostawa niesie nagłówek x-vigilae-signature: t=<unix>,v1=HMAC-SHA256(secret, t + "." + body). Przelicz v1 z surowego otrzymanego body i odrzuć każdy znacznik czasu t starszy niż 5 min: to ochrona anty-replay. Podczas rotacji sekretu nagłówek niesie jedno v1 na każdy wciąż ważny sekret (24 h nakładania się): zaakceptuj, jeśli którekolwiek się zgadza.

// Node — weryfikacja podpisu (bez zależności) 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; // anty-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 — ta sama weryfikacja 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 # anty-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

Przejściowo: stary format sha256=HMAC(body) jest nadal emitowany w x-vigilae-signature-legacy dla już działających odbiorników; jego usunięcie planowane jest wraz z webhookami v2. Nowe odbiorniki weryfikują powyższy schemat ze znacznikiem czasu, nie stary.

Rotację wyzwala się z konsoli (POST /connect/webhook/rotation po stronie aplikacji): przez 24 h stary sekret nadal podpisuje — czas na wdrożenie nowego po Twojej stronie bez okna awarii.

Widżety osadzone

Stan czujności, na Twoich ekranach.

Twoje oprogramowanie już tworzy sprawy przez API; widżety dają mu powierzchnię, której brakowało: pokazanie stanu czujności sprawy wprost na karcie klienta, bez budowania od nowa interfejsu zgodności. Cały przepływ to trzy kroki — Twój serwer wydaje krótkotrwały token, zwrócony URL trafia do iframe'a, widżet wyświetla. Wyświetlanie to jedyne, co robi: żadna decyzja, żadna kwalifikacja, żaden zapis nigdy nie przechodzi przez widżet. Kliknięcie otwiera aplikację Vigilae, gdzie działa zidentyfikowany człowiek.

1. Wydaj token — po stronie serwera, nigdy na stronie

Klucz vgk_ nigdy nie dotyka przeglądarki. Twój serwer wywołuje mint z dedykowanym uprawnieniem embed:emettre (zaznaczanym przy tworzeniu klucza, nigdy nie dziedziczonym) i tylko krótki token schodzi do strony: piętnaście minut domyślnie, w granicach 5-60, związany z jedną sprawą, jednym komponentem, jednym zadeklarowanym źródłem. Podróżuje we fragmencie URL — nie trafia ani do naszych logów, ani do Twoich.

# Token dla Compliance Button, etykieta wybrana z katalogu 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. Umieść iframe — launcher, w dziesięciu liniach

Launcher vigilae-embed.js tworzy wyizolowany iframe (sandbox), przeprowadza uzgadnianie i podąża za rozmiarem widżetu (ograniczonym — iframe nigdy nie narzuca swojej wysokości Twojej stronie). Jeśli chodzi o CSP, Twoja strona otwiera jedną jedyną dyrektywę: frame-src https://vigilae.org. Nie jest wymagany żaden skrypt inline, żadna zależność. Ręcznie napisany iframe działa równie dobrze.

<script src="https://vigilae.org/embarque/vigilae-embed.js" defer></script> <div id="vigilance"></div>
// W Twoim skrypcie: url pochodzi z TWOJEGO serwera, który wywołał mint var widget = VigilaeEmbed.monter({ conteneur: 'vigilance', url: urlReturnedByTheMint, renouvelerJeton: function () { // po wygaśnięciu: wydaj nowy token po stronie serwera return fetch('/my-server/vigilae-token').then(function (r) { return r.text(); }); }, }); // widget.rafraichir(token) wprowadza nowy token; widget.demonter() usuwa wszystko.

3. Compliance Button: Twoja etykieta, nasz stan

Etykieta przycisku pochodzi z zamkniętego katalogu — nigdy wolny tekst na powierzchni, która mówi o czujności; shell wyświetla te etykiety wyłącznie po francusku lub angielsku (parametr ?lang= w adresie URL widżetu), jeszcze nie w Twoim języku — poniższa lista podaje ich znaczenie:

  • controler_client — „Sprawdź tego klienta” (domyślnie)
  • lancer_vigilance — „Rozpocznij należytą staranność”
  • verifier_be — „Sprawdź beneficjentów rzeczywistych”
  • preparer_dossier — „Przygotuj sprawę AML/CFT”

Wskaźnik stanu natomiast pokazuje stan obliczony przez Vigilae: a_jour (zielony — weryfikacja sankcyjna i ocena ryzyka aktualne), a_revoir (bursztynowy — weryfikacja sankcyjna lub ocena ryzyka nieaktualne, albo źródło zawiodło przy ostatnim przebiegu), alerte (czerwony — co najmniej jeden alert do rozpatrzenia), inconnu (szary — sprawa nigdy nie sprawdzona). Etykieta jest konfigurowalna, semantyka nigdy: kolor jest związany ze stanem wewnątrz samego shellu, który ignoruje każdą próbę nadpisania go przez postMessage. Sprawa w stanie alertu pokazuje alert, niezależnie od stylizacji.

Kontrakt postMessage w całości

Widżet emituje vigilae:pret, vigilae:taille (automatyczne dopasowanie rozmiaru), vigilae:expire (wydaj nowy token po stronie serwera, a następnie wyślij vigilae:jeton) i vigilae:ouvrir. Nigdy żadnej nazwy, ryzyka ani alertu w wiadomości: Twoje oprogramowanie ma już wszystko przez API server-to-server, a ten kanał nie stanie się drugim takim kanałem.

Deklaracja źródeł: przez administratora Twojej kancelarii. Token embed jest związany z zadeklarowanym źródłem Twojej kancelarii — to ono steruje CSP frame-ancestors shellu. Administrator deklaruje je bezpośrednio w Vigilae, na ekranie „Integracje i bezpieczeństwo”: dziesięć źródeł https:// co najwyżej, jawny host, nigdy symbol wieloznaczny; komponenty, które włącza; oraz masowe unieważnienie, które jednym gestem unieważnia wszystkie już wydane tokeny. http://localhost jest dopuszczony wyłącznie w kancelarii testowej — napisz na contact@vigilae.org (temat „Embedded widgets”), aby otworzyć taką na czas Twojej integracji. Brak zadeklarowanego źródła: mint odmawia z kodem 400. Instancja, w której magazyn źródeł nie jest podłączony: jawne 501 — zobacz #embed-indisponible.
Środowisko testowe

Sandbox: na życzenie.

Samoobsługowego sandboksa jeszcze nie ma — wolimy napisać to tutaj, niż pozwolić Ci to odkryć samemu. Napisz na contact@vigilae.org (temat „API access”): otwieramy kancelarię testową z fikcyjnymi danymi na czas Twojej integracji i pozostajemy osiągalni, póki ta postępuje.

Każda klasa błędów API ma stały adres w katalogu błędów: #authentification, #scopes, #cloisonnement, #debit, #signature… Odpowiedzi błędów API będą wskazywać te kotwice.

API nie udostępnia ani zgłoszeń podejrzanych transakcji, ani dosłownych treści klienta — z samej konstrukcji (art. L.561-18 francuskiego CMF). API nie podejmuje żadnej decyzji w zakresie należytej staranności: udostępnia i kwalifikuje zdarzenia; decyduje osoba wykonująca zawód.