Vigilae Connect

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.

Omfanget

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

Nøgler med scopes, vist én gang, kan tilbagekaldes øjeblikkeligt.

  • Format. Hver nøgle begynder med vgk_ og sendes som Authorization: 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) og ecriture (skrivning), eller finkornede scopes, ressource for ressource — clients:, dossiers:, pieces:, criblage: (i lecture eller ecriture), origine-fonds:lecture, journal:lecture.
    Nedarvningen følger endelsen, og kun i én retning: lecture dækker alle *:lecture, ecriture alle *: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 (feltet coupure_le i GET /connect/cles), og hvert svar på et accepteret kald annoncerer den i headeren Sunset, 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-After og headerne X-RateLimit-Limit / -Remaining / -Reset.
  • Tilbagekaldelse. Øjeblikkelig, fra konsollen. Opslag sker via digest: nøgler kan ikke opregnes.
Quickstart

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.

Webhooks

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 False

Overgangsordning: 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.

Indlejrede widgets

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.

Angivelse af origins: ved Deres kontors administrator. En widget-token er bundet til en angivet origin for Deres kontor — det er den, der styrer shellets 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.
Testmiljø

Sandbox: på forespørgsel.

Der findes endnu ingen selvbetjenings-sandbox — vi vil hellere sige det her end lade Dem opdage det. Skriv til contact@vigilae.org (emne "API-adgang"): vi opretter et prøvekontor med fiktive data, så længe Deres integration varer, og vi er til at få fat på, mens den skrider frem.

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.