Un API pe care îl puteți citi înainte să semnați.
Specificația este publică, suprafețele sunt neutre, semnătura webhook-urilor se poate verifica în zece linii la dumneavoastră. Această pagină documentează ce expune API-ul astăzi — nimic mai mult, și asta în mod deliberat: ce nu este livrat nu este documentat.
- Specificație OpenAPI lizibilă fără cheie și fără cont
- Niciodată un raport de tranzacție suspectă, niciodată verbatim de client
- Webhook-uri semnate, verificabile în afara Vigilae
Servită chiar de API: contractul pe care îl citiți este cel care rulează.
Suprafețe neutre, prin construcție.
API-ul expune ceea ce un integrator poate consuma fără să atingă secretul dosarelor: jurnalul de monitorizare și contoare. Conținutul unui dosar de vigilență, documentele, rapoartele de tranzacție suspectă nu tranzitează acest API — nu este o limitare de abonament, ci arhitectura.
Jurnalul de monitorizare
Evenimentele pKYC ale cabinetului — document expirat, schimbare de beneficiar real, re-verificare de revăzut — în formă neutră: secvență, tip, severitate, dată. Răspunsuri întotdeauna plafonate la 500 de evenimente.
Agregate de portofoliu
Contoare, niciodată un dosar: volume pe statusuri, întârzieri, completitudine. Destul cât să afișați un tablou de bord în instrumentul dumneavoastră fără ca vreo dată de client să intre în el.
Calificare
Singura scriere: calificarea unui eveniment din jurnal (status qualifie sau clos, dispoziție planifie, traite sau ecarte). Necesită scope-ul de scriere — privilegiul minim este regula, nu o opțiune.
API-ul este gândit server-to-server: o cheie în cod livrat browserului este o cheie publicată. Lăsați un proxy pe server să țină cheia, niciodată pagina.
Chei cu acces delimitat, afișate o singură dată, revocabile imediat.
- Format. Fiecare cheie începe cu
vgk_și se trimite caAuthorization: Bearer vgk_…. Secretul este afișat doar la creare: nu păstrăm decât amprenta sa SHA-256. - Scope-uri.
lecture(citire, implicit) șiecriture(scriere). O cheie fără scope-ul necesar primește un 403 — vedeți #scopes. - Expirare. La un an de la creare (vizibilă în consola cabinetului). O cheie expirată primește un 401 explicit — vedeți #cle-expiree.
- Debit. 60 de cereri/minut per cheie (ajustabil per cheie). Un 429 poartă
Retry-Afterși anteteleX-RateLimit-Limit / -Remaining / -Reset. - Revocare. Imediată, din consolă. Rezolvarea se face prin amprentă: cheile nu pot fi enumerate.
Trei apeluri curl și ați văzut tot.
# Stare de funcționare + autentificarea cheii
curl -s https://vigilae.org/api/v1/sante \
-H "Authorization: Bearer vgk_cheia_dumneavoastra"
# Jurnalul de monitorizare, de la început, în pagini de câte 100
curl -s "https://vigilae.org/api/v1/evenements?depuisSeq=0&limite=100" \
-H "Authorization: Bearer vgk_cheia_dumneavoastra"
# Calificați evenimentul 42 (scope de scriere)
curl -s -X POST https://vigilae.org/api/v1/evenements/42/qualifier \
-H "Authorization: Bearer vgk_cheia_dumneavoastra" \
-H "Content-Type: application/json" \
-d '{"statut":"qualifie","disposition":"traite"}'Paginarea, într-o singură regulă
Transmiteți depuisSeq (0 la primul apel) și limite (plafonată la 500): răspunsul este sortat după seq crescător și returnează prochainSeq, de retransmis ca atare la apelul următor. O pagină mai scurtă decât limite înseamnă sfârșitul jurnalului — prochainSeq rămâne atunci stabil și servește drept cursor de interogare periodică. Fără depuisSeq, obțineți vederea „cele mai recente întâi”, plafonată la 500.
Portofoliul se interoghează pe /api/v1/portefeuille/agregats — contoare, un singur răspuns, fără paginare.
Semnate, cu marcaj temporal, livrate cel puțin o dată.
În loc să interogați jurnalul, primiți-l: Vigilae livrează evenimentele la URL-ul dumneavoastră, în ordine, în loturi de cel mult 100. Livrarea este at-least-once — cursorul avansează doar la 2xx-ul dumneavoastră, lot cu lot — iar idempotența se face după seq: procesați fiecare secvență exact o dată (#idempotence).
Verificarea semnăturii
Fiecare livrare poartă antetul x-vigilae-signature: t=<unix>,v1=HMAC-SHA256(secret, t + "." + body). Recalculați v1 din corpul brut primit și respingeți orice marcaj temporal t mai vechi de 5 min: acesta este mecanismul anti-replay. În timpul unei rotații de secret, antetul poartă câte un v1 pentru fiecare secret încă valid (suprapunere de 24 h): acceptați dacă oricare dintre ele se potrivește.
// Node — verificarea semnăturii (fără dependențe)
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 — aceeași verificare
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 FalseTranzitoriu: vechiul format sha256=HMAC(body) este încă emis pe x-vigilae-signature-legacy pentru receptoarele deja instalate; eliminarea sa este planificată odată cu webhook-urile v2. Receptoarele noi verifică schema cu marcaj temporal de mai sus, nu pe cea veche.
Rotația se declanșează din consolă (POST /connect/webhook/rotation pe partea aplicației): timp de 24 h vechiul secret încă semnează — răgaz să instalați noul secret la dumneavoastră, fără fereastră de eșec.
Sandbox: la cerere.
Fiecare clasă de erori API are o adresă stabilă în referința erorilor: #authentification, #scopes, #cloisonnement, #debit, #signature… Răspunsurile de eroare ale API-ului vor trimite către aceste ancore.
API-ul nu expune nici rapoarte de tranzacție suspectă, nici verbatim de client, prin construcție (art. L.561-18 din CMF francez). Nicio decizie de vigilență nu este luată de API: acesta expune și califică evenimente; profesionistul decide.