Ett API du kan läsa innan du skriver under.
Specifikationen är publik, webhooksignaturen kan verifieras på tio rader på din sida. Den här sidan dokumenterar vad API:t exponerar i dag — inget mer, och det är avsiktligt: det som inte är levererat är inte dokumenterat.
- OpenAPI-specifikation som kan läsas utan nyckel och utan konto
- Aldrig en rapport om misstänkt transaktion, aldrig ordagrant kundinnehåll
- Signerade webhookar, verifierbara utanför Vigilae
Serveras av API:t självt: kontraktet du läser är det som körs.
Hela ärendets gång — och två uteslutningar som inte rubbas.
Din programvara kan driva ett ärende från början till slut: skapa kunden, öppna ärendet, ladda upp handlingarna, köra screeningen, ange de verkliga huvudmännen, läsa riskvärderingen och hämta bevisakten. Två saker går aldrig den vägen, och det är ingen abonnemangsbegränsning: ingen rapport om misstänkta transaktioner och inget ordagrant innehåll från din kund. Det första är en handling som lagen förbehåller den som rapporterar; det andra hör inte hemma i en integrationskanal.
Ärendet, från början till slut
Kunder, ärenden, styrkande handlingar, screening, verkliga huvudmän, riskvärdering, bevisakt, dataintegritetskontroll. Varje resurs har sitt scope: din nyckel öppnar bara det du har gett den.
Övervakningsjournal och aggregat
Byråns pKYC-händelser — utgången handling, byte av verklig huvudman, omscreening att hantera — och portföljräknare till din instrumentpanel. Svaret är alltid begränsat, markören stabil.
Det du skriver bär ett namn
Ladda upp, screena, kvalificera: varje skrivning kräver sitt scope och registrerar operatören. En anonym kvalificering avvisas — integrationen registrerar ett mänskligt beslut, den fattar inget.
API:t är utformat för server-till-server: en nyckel i kod som skickas till webbläsaren är en publicerad nyckel. Låt en proxy på serversidan hålla nyckeln, aldrig sidan.
Nycklar med avgränsat scope, visade en gång, omedelbart återkallbara.
- Format. Varje nyckel börjar med
vgk_och skickas somAuthorization: Bearer vgk_…. Hemligheten visas bara när nyckeln skapas: vi behåller inget annat än dess SHA-256-hash. - Scope. En nyckel bär bara de scope som kryssades i när den skapades: de generella
lecture(läsning, standard) ochecriture(skrivning), eller finkorniga scope, resurs för resurs —clients:,dossiers:,pieces:,criblage:(ilectureellerecriture),origine-fonds:lecture,journal:lecture.
Arvet följer ändelsen och går bara åt ett håll:lecturetäcker varje*:lecture,ecriturevarje*:ecriture; ett finkornigt scope öppnar ingenting utöver sig självt.
Sex scope faller utanför det paret och ärvs därför från ingen generell nyckel:alertes:qualifier,embed:emettre,adversemedia:consulter,conformite:consulter,dispositif:consulter,integrite:consulter. Vart och ett delegeras för sig, när nyckeln skapas.
En nyckel utan det scope som krävs får 403 — se #scopes. - Utgång. Ett år efter skapandet (syns i byråns konsol). En utgången nyckel får en uttrycklig 401 — se #cle-expiree.
En nyckel kan också sluta godtas före detta datum, när API:t inte längre ingår i byråns abonnemang. Stoppet inträffar då minst 30 dagar efter ett första e-postmeddelande till byrån, på det datum som ett andra meddelande anger, skickat minst 7 dagar i förväg. Så snart datumet är fastställt syns det i byråns konsol (fältetcoupure_leiGET /connect/cles), och varje svar på ett godtaget anrop aviserar det i huvudetSunsettills det inträffar. Därefter får anropet den 401 som beskrivs under #authentification, med"motif": "fin_option_api"; ingår API:t i abonnemanget igen godtas nyckeln igen, fram till sitt eget utgångsdatum.
En återkallad nyckel kommer inte tillbaka med API:t. Och när hela abonnemanget stängs av eller upphör slutar nycklarna godtas omedelbart, utan denna frist. - Anropstakt. 60 anrop/minut per nyckel (kan justeras per nyckel). En 429 bär
Retry-Afteroch huvudenaX-RateLimit-Limit / -Remaining / -Reset. - Återkallelse. Omedelbar, från konsolen. Uppslagningen sker via hash: nycklar kan inte räknas upp.
Tre curl-anrop och du har sett allt.
# Hälsa + nyckelautentisering
curl -s https://vigilae.org/api/v1/sante \
-H "Authorization: Bearer vgk_your_key"
# Övervakningsjournalen, från början, i sidor om 100
curl -s "https://vigilae.org/api/v1/evenements?depuisSeq=0&limite=100" \
-H "Authorization: Bearer vgk_your_key"
# Kvalificera händelse 42 (skrivscope)
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"}'Paginering, i en regel
Skicka depuisSeq (0 vid första anropet) och limite (högst 500): svaret sorteras efter stigande seq och returnerar prochainSeq, som skickas tillbaka oförändrad vid nästa anrop. En sida kortare än limite betyder journalens slut — prochainSeq förblir då stabil och fungerar som pollningsmarkör. Utan depuisSeq får du vyn ”senaste först”, begränsad till 500.
Portföljen frågas på /api/v1/portefeuille/agregats — räknare, ett svar, ingen paginering.
Signerade, tidsstämplade, levererade minst en gång.
I stället för att polla journalen kan du ta emot den: Vigilae levererar händelser till din URL, i ordning, i omgångar om högst 100. Leveransen är at-least-once — markören flyttas bara fram vid din 2xx, omgång för omgång — och idempotensen bygger på seq: behandla varje sekvens exakt en gång (#idempotence).
Verifiera signaturen
Varje leverans bär huvudet x-vigilae-signature: t=<unix>,v1=HMAC-SHA256(secret, t + "." + body). Räkna om v1 från den råa kropp som togs emot, och avvisa varje tidsstämpel t äldre än 5 min: det är anti-replay-skyddet. Under en hemlighetsrotation bär huvudet ett v1 per ännu giltig hemlighet (24 h överlappning): acceptera om någon av dem stämmer.
// Node — signaturverifiering (utan beroenden)
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 — samma verifiering
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Övergångsvis: det gamla formatet sha256=HMAC(body) sänds fortfarande på x-vigilae-signature-legacy för mottagare som redan är på plats; borttagningen planeras till webhooks v2. Nya mottagare verifierar det tidsstämplade schemat ovan, inte det gamla.
Rotationen utlöses från konsolen (POST /connect/webhook/rotation på applikationssidan): i 24 h signerar den gamla hemligheten fortfarande — tid att driftsätta den nya på din sida utan ett felfönster.
Övervakningsstatus, mitt i era skärmar.
Er programvara skapar redan ärendena via API:t; widgetar ger den ytan som saknades: att visa ett ärendes övervakningsstatus i er kundpost, utan att bygga ett eget gränssnitt för regelefterlevnad. Flödet tar tre steg — er server utfärdar en kortlivad token, den returnerade URL:en läggs i en iframe, widgeten visar. Den visar, och det är allt den gör: inget beslut, ingen kvalificering, ingen skrivning går någonsin via en widget. Klicket öppnar Vigilae-applikationen, där en identifierad person agerar.
1. Utfärda en token — på serversidan, aldrig på sidan
vgk_-nyckeln berör aldrig webbläsaren. Er server anropar utfärdandet med det dedikerade scopet embed:emettre (kryssat vid nyckelns skapande, aldrig ärvt), och bara en kort token går vidare till sidan: femton minuter som standard, begränsad till 5–60, knuten till ett ärende, en komponent, ett angivet ursprung. Den reser i URL-fragmentet — den når varken våra loggar eller era.
# En token för Compliance Button, etikett vald från katalogen
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. Placera iframen — lanseringsskriptet, på tio rader
Lanseringsskriptet vigilae-embed.js skapar den sandboxade iframen, utför handskakningen och följer widgetens storlek (begränsad — iframen dikterar aldrig sin höjd till er sida). CSP-mässigt öppnar er sida bara en enda direktiv: frame-src https://vigilae.org. Inget inline-skript krävs, inget beroende. En handskriven iframe fungerar precis lika bra.
<script src="https://vigilae.org/embarque/vigilae-embed.js" defer></script>
<div id="vigilance"></div>// I ert skript: url:en kommer från ER server, som anropade utfärdandet
var widget = VigilaeEmbed.monter({
conteneur: 'vigilance',
url: urlReturnedByTheMint,
renouvelerJeton: function () { // vid utgång: utfärda ny token på serversidan
return fetch('/my-server/vigilae-token').then(function (r) { return r.text(); });
},
});
// widget.rafraichir(token) skickar en ny token; widget.demonter() tar bort allt.3. Compliance Button: er etikett, vårt tillstånd
Etiketten på knappen väljs ur en stängd katalog — aldrig fri text på en yta som talar om övervakning. Skalet visar dem bara på franska eller engelska (parametern ?lang=), ännu inte på ert språk — listan nedan ger innebörden:
controler_client— ”Kontrollera denna kund” (standard)lancer_vigilance— ”Starta kundkännedomen”verifier_be— ”Kontrollera verkliga huvudmän”preparer_dossier— ”Förbered penningtvättsärendet”
Statusindikatorn, däremot, visar ett tillstånd beräknat av Vigilae: a_jour (grön — screening och riskklassificering aktuella), a_revoir (gul — screening eller riskklassificering inaktuell, eller källan misslyckades vid senaste körningen), alerte (röd — minst ett larm att granska), inconnu (grå — ärende aldrig screenat). Etiketten konfigureras. Semantiken, aldrig: färgen är knuten till tillståndet inuti själva skalet, som ignorerar varje försök att åsidosätta den via postMessage. Ett ärende i larmläge visar larm, oavsett utseende.
postMessage-kontraktet, i sin helhet
Widgeten sänder ut vigilae:pret, vigilae:taille (automatisk storleksanpassning), vigilae:expire (utfärda ny token på serversidan, posta sedan vigilae:jeton) och vigilae:ouvrir. Aldrig ett namn, en risk eller ett larm i ett meddelande: er programvara har redan allt via server-till-server-API:t, och den här kanalen blir inte en andra.
frame-ancestors i skalet. Administratören anger det direkt i Vigilae, på skärmen ”Integrationer och säkerhet”: högst tio https://-ursprung, uttalad värd, aldrig jokertecken; de komponenter som administratören aktiverar; och en massåterkallelse som i ett enda steg dödar alla redan utfärdade tokens. http://localhost är endast tillåtet för en sandbox-byrå — skriv till contact@vigilae.org (ämne ”Inbäddade widgetar”) för att få en sådan öppnad under hela er integration. Inget angivet ursprung: utfärdandet nekar med 400. En instans vars ursprungslagring inte är kopplad: en uttrycklig 501 — se #embed-indisponible.Sandbox: på begäran.
Varje felklass i API:t har en stabil adress i felreferensen: #authentification, #scopes, #cloisonnement, #debit, #signature… API:ts felsvar kommer att peka på dessa ankare.
API:t exponerar varken rapporter om misstänkta transaktioner eller ordagrant kundinnehåll, genom själva konstruktionen (art. L.561-18 i den franska CMF). Inget vaksamhetsbeslut fattas av API:t: det exponerar och kvalificerar händelser; yrkesutövaren beslutar.