Et API, De kan læse, før De skriver under.
Specifikationen er offentlig, webhook-signaturen kan verificeres på ti linjer hos Dem. Denne side dokumenterer, hvad API'et eksponerer i dag — intet mere, og det er med vilje: hvad der ikke er leveret, er ikke dokumenteret.
- OpenAPI-specifikation, der kan læses uden nøgle eller konto
- Aldrig en underretning om mistænkelig transaktion, aldrig ordret kundeindhold
- Signerede webhooks, der kan verificeres uden for Vigilae
Serveret af API'et selv: den kontrakt, De læser, er den, der kører.
Hele sagens gang — og to udelukkelser, der ikke rykker sig.
Deres software kan føre en sag fra ende til anden: oprette kunden, åbne sagen, uploade bilagene, køre screeningen, angive de reelle ejere, læse risikoklassificeringen og hente bevismaterialet. To ting går aldrig den vej, og det er ikke en abonnementsbegrænsning: ingen underretning om mistænkelige transaktioner og intet ordret indhold fra Deres kunde. Det første er en handling, som loven forbeholder den, der underretter; det andet hører ikke hjemme i en integrationskanal.
Sagen, fra ende til anden
Kunder, sager, bilag, screening, reelle ejere, risikoklassificering, bevismateriale, integritetskontrol. Hver ressource har sit scope: Deres nøgle åbner kun det, De har givet den.
Overvågningsjournal og aggregater
Kontorets pKYC-hændelser — udløbet bilag, ændring af reel ejer, re-screening til behandling — og porteføljetællere til Deres dashboard. Svaret er altid begrænset, cursoren stabil.
Det, De skriver, bærer et navn
Uploade, screene, kvalificere: hver skrivning kræver sit scope og registrerer operatøren. En anonym kvalificering afvises — integrationen registrerer en menneskelig beslutning, den træffer ingen.
API'et er designet server-til-server: en nøgle i kode, der sendes til browseren, er en offentliggjort nøgle. Lad en server-side proxy holde nøglen, aldrig siden.
Nøgler med scopes, vist én gang, kan tilbagekaldes øjeblikkeligt.
- Format. Hver nøgle begynder med
vgk_og sendes somAuthorization: Bearer vgk_…. Hemmeligheden vises kun ved oprettelsen: vi opbevarer intet andet end dens SHA-256-digest. - Scopes. En nøgle bærer kun de scopes, der blev sat ved oprettelsen: de generelle
lecture(læsning, standard) ogecriture(skrivning), eller finkornede scopes, ressource for ressource —clients:,dossiers:,pieces:,criblage:(ilectureellerecriture),origine-fonds:lecture,journal:lecture.
Nedarvningen følger endelsen, og kun i én retning:lecturedækker alle*:lecture,ecriturealle*:ecriture; et finkornet scope åbner intet ud over sig selv.
Seks scopes falder uden for det par og nedarves derfor fra ingen generel nøgle:alertes:qualifier,embed:emettre,adversemedia:consulter,conformite:consulter,dispositif:consulter,integrite:consulter. De uddelegeres ét ad gangen, når nøglen oprettes.
En nøgle uden det krævede scope modtager en 403 — se #scopes. - Udløb. Ét år efter oprettelsen (synligt i kontorets konsol). En udløbet nøgle modtager en eksplicit 401 — se #cle-expiree.
En nøgle kan også holde op med at blive accepteret før denne dato, når API'et ikke længere er en del af kontorets abonnement. Stoppet falder da mindst 30 dage efter en første e-mail til kontoret, på den dato, som en anden e-mail oplyser, sendt mindst 7 dage i forvejen. Så snart datoen er fastsat, kan den ses i kontorets konsol (feltetcoupure_leiGET /connect/cles), og hvert svar på et accepteret kald annoncerer den i headerenSunset, indtil den indtræffer. Efter denne dato får kaldet den 401, der er beskrevet under #authentification, med"motif": "fin_option_api"; kommer API'et med i abonnementet igen, accepteres nøglen igen, indtil dens egen udløbsdato.
En tilbagekaldt nøgle kommer ikke tilbage med API'et. Og når hele abonnementet suspenderes eller ophører, holder nøglerne straks op med at blive accepteret, uden denne frist. - Rategrænse. 60 forespørgsler/minut pr. nøgle (kan tilpasses pr. nøgle). En 429 bærer
Retry-Afterog headerneX-RateLimit-Limit / -Remaining / -Reset. - Tilbagekaldelse. Øjeblikkelig, fra konsollen. Opslag sker via digest: nøgler kan ikke opregnes.
Tre curl-kald, og De har set det hele.
# Sundhedstjek + nøgleautentificering
curl -s https://vigilae.org/api/v1/sante \
-H "Authorization: Bearer vgk_your_key"
# Overvågningsjournal, fra begyndelsen, i sider af 100
curl -s "https://vigilae.org/api/v1/evenements?depuisSeq=0&limite=100" \
-H "Authorization: Bearer vgk_your_key"
# Kvalificer hændelse 42 (skrive-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"}'Paginering, i én regel
Send depuisSeq (0 ved første kald) og limite (loft på 500): svaret er sorteret efter stigende seq og returnerer prochainSeq, som sendes tilbage uændret ved næste kald. En side kortere end limite betyder journalens slutning — prochainSeq forbliver da stabil og fungerer som polling-cursor. Uden depuisSeq får De visningen "nyeste først", begrænset til 500.
Porteføljen forespørges på /api/v1/portefeuille/agregats — tællere, ét svar, ingen paginering.
Signerede, tidsstemplede, leveret mindst én gang.
I stedet for at polle journalen: modtag den. Vigilae leverer hændelser til Deres URL, i rækkefølge, i batches på højst 100. Leveringen er at-least-once — cursoren rykker kun frem ved Deres 2xx, batch for batch — og idempotens sker pr. seq: behandl hver sekvens præcis én gang (#idempotence).
Verificering af signaturen
Hver levering bærer headeren x-vigilae-signature: t=<unix>,v1=HMAC-SHA256(secret, t + "." + body). Genberegn v1 ud fra den rå body, De har modtaget, og afvis ethvert tidsstempel t ud over 5 min.: det er anti-replay-værnet. Under en rotation af hemmeligheden bærer headeren én v1 pr. stadig gyldig hemmelighed (24 timers overlap): acceptér, hvis blot én af dem matcher.
// Node — signaturverificering (ingen afhængigheder)
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 — samme verificering
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 FalseOvergangsordning: det gamle format sha256=HMAC(body) udsendes stadig på x-vigilae-signature-legacy til allerede etablerede modtagere; fjernelsen er planlagt sammen med webhooks v2. Nye modtagere verificerer det tidsstemplede skema ovenfor, ikke det gamle.
Rotationen udløses fra konsollen (POST /connect/webhook/rotation på applikationssiden): i 24 timer signerer den gamle hemmelighed stadig — tid til at udrulle den nye hos Dem uden et fejlvindue.
Vigilansstatus, i Deres skærmbilleder.
Deres software opretter allerede sagerne via API'et; widgets giver den flade, der manglede: at vise en sags vigilansstatus i Deres kundekort, uden at genopbygge en compliance-brugerflade. Forløbet tager tre trin — Deres server udsteder en kortvarig token, den returnerede URL lægges i en iframe, widgetten viser. Den gør kun dét: ingen beslutning, ingen kvalificering, ingen skrivning går nogensinde gennem en widget. Et klik åbner Vigilae-applikationen, hvor et identificeret menneske handler.
1. Udsted tokenen — server-side, aldrig i siden
Nøglen vgk_ rører aldrig browseren. Deres server kalder udstedelsen med det dedikerede scope embed:emettre (afkrydset ved oprettelse af nøglen, aldrig nedarvet), og kun den korte token sendes videre til siden: femten minutter som standard, begrænset til 5-60, bundet til én sag, én komponent, én angivet origin. Den rejser i URL-fragmentet — den når hverken vores logs eller Deres.
# En token til Compliance Button, etiket valgt fra kataloget
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. Indsæt iframen — launcheren, på ti linjer
Launcheren vigilae-embed.js opretter sandbox-iframen, udfører handshaket og følger widgettens størrelse (begrænset — iframen dikterer aldrig sin højde til Deres side). CSP-mæssigt åbner Deres side kun én direktiv: frame-src https://vigilae.org. Intet inline-script krævet, ingen afhængighed. En håndskrevet iframe fungerer lige så godt.
<script src="https://vigilae.org/embarque/vigilae-embed.js" defer></script>
<div id="vigilance"></div>// I Deres script: url'en kommer fra DERES server, som stod for udstedelsen
var widget = VigilaeEmbed.monter({
conteneur: 'vigilance',
url: urlReturnedByTheMint,
renouvelerJeton: function () { // ved udløb: genudsted server-side
return fetch('/my-server/vigilae-token').then(function (r) { return r.text(); });
},
});
// widget.rafraichir(token) sender en frisk token videre; widget.demonter() fjerner alt.3. Compliance Button: Deres etiket, vores status
Knappens etiket vælges fra et lukket katalog — aldrig fri tekst på en flade, der taler om vigilans; shellet viser dem kun på fransk eller engelsk (parameteren ?lang=), endnu ikke på dansk — listen nedenfor angiver betydningen:
controler_client— "Kontrollér denne kunde" (standard)lancer_vigilance— "Start vigilans"verifier_be— "Kontrollér reelle ejere"preparer_dossier— "Forbered AML-sagen"
Statusprikken derimod viser en status beregnet af Vigilae: a_jour (grøn — screening og scoring opdateret), a_revoir (orange — screening eller scoring forældet, eller kilden fejlede ved seneste kørsel), alerte (rød — mindst én advarsel at gennemgå), inconnu (grå — sag aldrig screenet). Etiketten er konfigurerbar — semantikken er det aldrig: farven er bundet til statussen inde i selve shellet, som ignorerer ethvert forsøg på at overstyre den via postMessage. En sag med advarsel viser advarsel, uanset stylingen.
postMessage-kontrakten, i sin helhed
Widgetten udsender vigilae:pret, vigilae:taille (automatisk størrelsestilpasning), vigilae:expire (genudsted server-side, send derefter vigilae:jeton) og vigilae:ouvrir. Aldrig et navn, en risiko eller en advarsel i en besked: Deres software har allerede alt via server-til-server-API'et, og denne kanal bliver ikke til endnu en.
frame-ancestors-CSP. Administratoren angiver den direkte i Vigilae, på skærmen "Integrationer og sikkerhed": højst ti https:// origins, eksplicit vært, aldrig et jokertegn; de komponenter, vedkommende aktiverer; samt en samlet tilbagekaldelse, der dræber alle allerede udstedte tokens i ét greb. http://localhost er kun tilladt på et sandbox-kontor — skriv til contact@vigilae.org (emne "Indlejrede widgets") for at få ét åbnet, så længe Deres integration varer. Ingen origin angivet: udstedelsen afviser med en 400. En instans, hvor origin-lagringen ikke er tilkoblet: en eksplicit 501 — se #embed-indisponible.Sandbox: på forespørgsel.
Hver fejlklasse i API'et har en stabil adresse i fejlreferencen: #authentification, #scopes, #cloisonnement, #debit, #signature… API'ets fejlsvar vil pege på disse ankre.
API'et eksponerer hverken underretninger om mistænkelige transaktioner eller ordret kundeindhold, i selve konstruktionen (art. L.561-18 i den franske CMF). Ingen vigilansbeslutning træffes af API'et: det eksponerer og kvalificerer hændelser; fagpersonen beslutter.