Eine API, die Sie lesen können, bevor Sie unterschreiben.
Die Spezifikation ist öffentlich, die Webhook-Signatur lässt sich in zehn Zeilen auf Ihrer Seite prüfen. Diese Seite dokumentiert, was die API heute bereitstellt — nicht mehr, und das ist Absicht: Was nicht ausgeliefert ist, wird nicht dokumentiert.
- OpenAPI-Spezifikation lesbar ohne Schlüssel und ohne Konto
- Niemals eine Verdachtsmeldung, niemals Kundenwortlaut
- Signierte Webhooks, prüfbar außerhalb von Vigilae
Von der API selbst ausgeliefert: Der Vertrag, den Sie lesen, ist der, der läuft.
Der gesamte Prozess – und zwei Ausschlüsse, an denen sich nichts ändert.
Ihre Software kann ein Dossier von A bis Z führen: den Kunden anlegen, das Dossier eröffnen, die Unterlagen hochladen, das Screening starten, die wirtschaftlich Berechtigten angeben, die Risikobewertung lesen und das Nachweisdossier abrufen. Zwei Dinge laufen niemals darüber, und das ist keine Tarifgrenze: keine Verdachtsmeldung und kein Wortlaut Ihres Kunden. Das Erste ist ein Akt, den das Gesetz der meldenden Person vorbehält; das Zweite hat in einer Integrationsschnittstelle nichts zu suchen.
Das Dossier, von A bis Z
Kunden, Dossiers, Belege, Screening, wirtschaftlich Berechtigte, Risikobewertung, Nachweisdossier, Integritätsprüfung. Jede Ressource hat ihren Scope: Ihr Schlüssel öffnet nur das, was Sie ihm mitgegeben haben.
Journal und Aggregate
Die pKYC-Ereignisse der Kanzlei — abgelaufenes Dokument, Wechsel des wirtschaftlich Berechtigten, zu prüfendes Re-Screening — und Portfolio-Zähler für Ihr Dashboard. Antwort stets begrenzt, Cursor stabil.
Was Sie schreiben, trägt einen Namen
Hochladen, Screenen, Qualifizieren: Jeder Schreibzugriff verlangt seinen Scope und protokolliert den Betreiber. Eine anonyme Qualifizierung wird abgelehnt — die Integration hält eine menschliche Entscheidung fest, sie trifft selbst keine.
Die API ist Server-zu-Server ausgelegt: Ein Schlüssel in Code, der an den Browser ausgeliefert wird, ist ein veröffentlichter Schlüssel. Lassen Sie einen serverseitigen Proxy den Schlüssel halten, nie die Seite.
Schlüssel mit Scopes, einmal angezeigt, sofort widerrufbar.
- Format. Jeder Schlüssel beginnt mit
vgk_und wird alsAuthorization: Bearer vgk_…gesendet. Das Geheimnis wird nur bei der Erstellung angezeigt: Wir bewahren nichts als seinen SHA-256-Digest auf. - Scopes. Ein Schlüssel trägt nur die bei seiner Erstellung angekreuzten Scopes: die allgemeinen
lecture(Lesen, der Standard) undecriture(Schreiben), oder feingranulare, Ressource für Ressource —clients:,dossiers:,pieces:,criblage:(jeweils inlectureoderecriture),origine-fonds:lecture,journal:lecture.
Die Vererbung folgt dem Suffix, und nur in eine Richtung:lecturedeckt jedes*:lectureab,ecriturejedes*:ecriture; ein feingranularer Scope öffnet nichts über sich selbst hinaus.
Sechs Scopes fallen aus diesem Paar heraus und werden daher von keinem allgemeinen Schlüssel geerbt:alertes:qualifier,embed:emettre,adversemedia:consulter,conformite:consulter,dispositif:consulter,integrite:consulter. Jeder wird einzeln delegiert, bei der Erstellung des Schlüssels.
Ein Schlüssel ohne den erforderlichen Scope erhält einen 403 — siehe #scopes. - Ablauf. Ein Jahr nach der Erstellung (sichtbar in der Konsole der Kanzlei). Ein abgelaufener Schlüssel erhält einen expliziten 401 — siehe #cle-expiree.
Ein Schlüssel kann auch vor diesem Datum nicht mehr angenommen werden, wenn die API nicht mehr Teil des Abonnements der Kanzlei ist. Der Stopp erfolgt dann mindestens 30 Tage nach einer ersten E-Mail an die Kanzlei, an dem Datum, das eine zweite E-Mail nennt, die mindestens 7 Tage vorher verschickt wird. Sobald es feststeht, ist dieses Datum in der Konsole der Kanzlei sichtbar (Feldcoupure_levonGET /connect/cles), und jede Antwort auf einen angenommenen Aufruf kündigt es im HeaderSunsetan, bis es erreicht ist. Danach erhält der Aufruf den 401 aus #authentification, mit"motif": "fin_option_api"; ist die API wieder Teil des Abonnements, wird der Schlüssel wieder angenommen, bis zu seinem eigenen Ablaufdatum.
Ein widerrufener Schlüssel kehrt mit der API nicht zurück. Und wird das gesamte Abonnement ausgesetzt oder endet es, werden die Schlüssel sofort nicht mehr angenommen, ohne diese Frist. - Rate. 60 Anfragen/Minute je Schlüssel (je Schlüssel anpassbar). Ein 429 trägt
Retry-Afterund die HeaderX-RateLimit-Limit / -Remaining / -Reset. - Widerruf. Sofort, aus der Konsole. Die Auflösung erfolgt über den Digest: Schlüssel lassen sich nicht enumerieren.
Drei curl-Aufrufe, und Sie haben alles gesehen.
# Health-Check + Schlüssel-Authentifizierung
curl -s https://vigilae.org/api/v1/sante \
-H "Authorization: Bearer vgk_your_key"
# Überwachungsjournal, von Anfang an, in Seiten zu 100
curl -s "https://vigilae.org/api/v1/evenements?depuisSeq=0&limite=100" \
-H "Authorization: Bearer vgk_your_key"
# Ereignis 42 qualifizieren (Schreib-Scope)
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"}'Paginierung, in einer Regel
Übergeben Sie depuisSeq (0 beim ersten Aufruf) und limite (gedeckelt bei 500): Die Antwort ist nach aufsteigender seq sortiert und liefert prochainSeq, das beim nächsten Aufruf unverändert zurückzugeben ist. Eine Seite kürzer als limite bedeutet das Ende des Journals — prochainSeq bleibt dann stabil und dient als Polling-Cursor. Ohne depuisSeq erhalten Sie die Ansicht „Neueste zuerst“, begrenzt auf 500.
Das Portfolio wird über /api/v1/portefeuille/agregats abgefragt — Zähler, eine Antwort, keine Paginierung.
Signiert, zeitgestempelt, mindestens einmal zugestellt.
Statt das Journal zu pollen, empfangen Sie es: Vigilae stellt Ereignisse an Ihre URL zu, in Reihenfolge, in Batches von höchstens 100. Die Zustellung ist at-least-once — der Cursor rückt nur auf Ihr 2xx vor, Batch für Batch — und die Idempotenz läuft über seq: Verarbeiten Sie jede Sequenz genau einmal (#idempotence).
Die Signatur prüfen
Jede Zustellung trägt den Header x-vigilae-signature: t=<unix>,v1=HMAC-SHA256(secret, t + "." + body). Berechnen Sie v1 aus dem rohen empfangenen Body neu und verwerfen Sie jeden Zeitstempel t jenseits von 5 min: Das ist der Anti-Replay. Während einer Secret-Rotation trägt der Header ein v1 je noch gültigem Secret (24 h Überlappung): Akzeptieren Sie, wenn eines davon passt.
// Node — Signaturprüfung (ohne Abhängigkeit)
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 — dieselbe Prüfung
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Übergangsweise: Das alte Format sha256=HMAC(body) wird für bereits bestehende Empfänger weiterhin auf x-vigilae-signature-legacy ausgegeben; seine Entfernung ist mit den Webhooks v2 geplant. Neue Empfänger prüfen das zeitgestempelte Schema oben, nicht das alte.
Die Rotation wird aus der Konsole ausgelöst (POST /connect/webhook/rotation auf Anwendungsseite): 24 h lang signiert das alte Secret weiter — Zeit, das neue auf Ihrer Seite auszurollen, ohne Ausfallfenster.
Der Überwachungsstatus, in Ihren Bildschirmen.
Ihre Software erstellt die Dossiers bereits über die API; die Widgets geben ihr die Oberfläche, die noch fehlte: den Überwachungsstatus eines Dossiers in Ihrem Kundendatensatz zu zeigen, ohne eine Compliance-Oberfläche neu aufzubauen. Der Ablauf verläuft in drei Schritten — Ihr Server stellt einen kurzlebigen Token aus, die zurückgegebene URL kommt in ein iframe, das Widget zeigt an. Mehr tut es nicht: keine Entscheidung, keine Qualifizierung, kein Schreibvorgang läuft je über ein Widget. Der Klick öffnet die Vigilae-Anwendung, in der ein identifizierter Mensch handelt.
1. Den Token ausstellen — serverseitig, nie in der Seite
Der Schlüssel vgk_ berührt nie den Browser. Ihr Server ruft den Mint mit dem dedizierten Scope embed:emettre auf (bei der Schlüsselerstellung angekreuzt, nie vererbt), und nur der kurze Token geht an die Seite: fünfzehn Minuten standardmäßig, begrenzt auf 5-60, gebunden an ein Dossier, eine Komponente, eine deklarierte Origin. Er reist im URL-Fragment — er erreicht weder unsere Logs noch Ihre.
# Ein Token für den Compliance Button, Beschriftung aus dem Katalog gewählt
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. Das iframe einsetzen — der Launcher, in zehn Zeilen
Der vigilae-embed.js-Launcher erzeugt das sandboxed iframe, führt den Handshake aus und folgt der Größe des Widgets (begrenzt — das iframe schreibt Ihrer Seite nie seine Höhe vor). CSP-seitig öffnet Ihre Seite nur eine Direktive: frame-src https://vigilae.org. Kein Inline-Skript nötig, keine Abhängigkeit. Ein handgeschriebenes iframe funktioniert genauso gut.
<script src="https://vigilae.org/embarque/vigilae-embed.js" defer></script>
<div id="vigilance"></div>// In Ihrem Skript: Die URL stammt von IHREM Server, der den Token ausgestellt hat
var widget = VigilaeEmbed.monter({
conteneur: 'vigilance',
url: urlReturnedByTheMint,
renouvelerJeton: function () { // bei Ablauf: serverseitig neu ausstellen
return fetch('/my-server/vigilae-token').then(function (r) { return r.text(); });
},
});
// widget.rafraichir(token) übergibt einen frischen Token; widget.demonter() entfernt alles.3. Der Compliance Button: Ihre Beschriftung, unser Status
Die Beschriftung des Buttons stammt aus einem geschlossenen Katalog — nie Freitext auf einer Compliance-Oberfläche; die Shell zeigt sie nur auf Französisch oder Englisch an (Parameter ?lang=), noch nicht auf Deutsch — die Liste unten gibt jeweils den Sinn wieder:
controler_client— „Diesen Kunden prüfen“ (Standard)lancer_vigilance— „Sorgfaltsprüfung starten“verifier_be— „Wirtschaftlich Berechtigte prüfen“preparer_dossier— „Das Dossier zur Geldwäscheprävention vorbereiten“
Der Statuspunkt zeigt dagegen einen von Vigilae berechneten Zustand: a_jour (grün — Screening und Bewertung aktuell), a_revoir (orange — Screening oder Bewertung veraltet, oder Quelle beim letzten Durchlauf fehlgeschlagen), alerte (rot — mindestens ein Alert zu prüfen), inconnu (grau — Dossier nie gescreent). Die Beschriftung ist konfigurierbar, die Semantik nie: Die Farbe ist innerhalb der Shell selbst fest an den Zustand gekoppelt — jeder Versuch, sie per postMessage zu überschreiben, wird ignoriert. Ein Dossier im Alarmzustand zeigt Alarm, unabhängig vom Styling.
Der postMessage-Vertrag, vollständig
Das Widget sendet vigilae:pret, vigilae:taille (automatische Größenanpassung), vigilae:expire (serverseitig neu ausstellen, dann vigilae:jeton posten) und vigilae:ouvrir. Nie ein Name, ein Risiko oder ein Alert in einer Nachricht: Ihre Software hat über die Server-zu-Server-API bereits alles, und dieser Kanal wird kein zweiter davon.
frame-ancestors-CSP der Shell. Der Administrator deklariert sie direkt in Vigilae, auf dem Bildschirm „Integrationen & Sicherheit“: höchstens zehn https://-Origins, expliziter Host, nie eine Wildcard; die Komponenten, die er aktiviert; und ein Massenwiderruf, der mit einer Geste alle bereits ausgestellten Token killt. http://localhost ist nur bei einer Sandbox-Kanzlei zulässig — schreiben Sie an contact@vigilae.org (Betreff „Eingebettete Widgets“), um für die Dauer Ihrer Integration eine öffnen zu lassen. Keine Origin deklariert: Der Mint verweigert mit einem 400. Eine Instanz, deren Origin-Speicher nicht angebunden ist: ein expliziter 501 — siehe #embed-indisponible.Sandbox: auf Anfrage.
Jede Fehlerklasse der API hat eine stabile Adresse in der Fehlerreferenz: #authentification, #scopes, #cloisonnement, #debit, #signature… Die Fehlerantworten der API werden auf diese Anker verweisen.
Die API stellt konstruktionsbedingt weder Verdachtsmeldungen noch Kundenwortlaut bereit (Art. L.561-18 CMF). Keine Sorgfaltsentscheidung wird von der API getroffen: Sie stellt Ereignisse bereit und qualifiziert sie; der Berufsträger entscheidet.