API, które można przeczytać przed podpisaniem.
Specyfikacja jest publiczna, powierzchnie neutralne, a podpis webhooka można zweryfikować w dziesięciu linijkach po swojej stronie. Ta strona dokumentuje to, co API udostępnia dziś — nic więcej, i to celowo: czego nie wdrożono, tego nie dokumentujemy.
- Specyfikacja OpenAPI czytelna bez klucza i bez konta
- Nigdy zgłoszenie podejrzanej transakcji, nigdy dosłowne treści klienta
- Podpisane webhooki, weryfikowalne poza Vigilae
Serwowana przez samo API: kontrakt, który czytasz, to ten, który działa.
Powierzchnie neutralne z samej konstrukcji.
API udostępnia to, co integrator może konsumować bez naruszania tajemnicy spraw: dziennik monitoringu i liczniki. Treść sprawy należytej staranności, dokumenty, zgłoszenia podejrzanych transakcji nie przechodzą przez to API — to nie ograniczenie planu, to architektura.
Dziennik monitoringu
Zdarzenia pKYC kancelarii — wygasły dokument, zmiana beneficjenta rzeczywistego, ponowna weryfikacja do przejrzenia — w neutralnej formie: sekwencja, typ, waga, data. Odpowiedzi zawsze ograniczone do 500 zdarzeń.
Agregaty portfela
Liczniki, nigdy sprawa: wolumeny według statusu, opóźnienia, kompletność. Tyle, ile trzeba, by wyrenderować pulpit w Twoim narzędziu — bez ani jednej danej klienta, która by do niego trafiła.
Kwalifikacja
Jedyny zapis: kwalifikacja zdarzenia z dziennika (status qualifie lub clos, dyspozycja planifie, traite lub ecarte). Wymaga uprawnienia zapisu — zasada najmniejszych uprawnień to reguła, nie opcja.
API jest zaprojektowane server-to-server: klucz w kodzie wysłanym do przeglądarki to klucz opublikowany. Klucz niech trzyma proxy po stronie serwera, nigdy strona.
Klucze o ograniczonych uprawnieniach, pokazywane raz, odwoływalne natychmiast.
- Format. Każdy klucz zaczyna się od
vgk_i jest przesyłany jakoAuthorization: Bearer vgk_…. Sekret jest pokazywany wyłącznie przy utworzeniu: przechowujemy jedynie jego skrót SHA-256. - Uprawnienia (scopes).
lecture(odczyt, domyślne) iecriture(zapis). Klucz bez wymaganego uprawnienia otrzymuje 403 — zob. #scopes. - Ważność. Rok od utworzenia (data widoczna w konsoli kancelarii). Wygasły klucz otrzymuje jednoznaczne 401 — zob. #cle-expiree.
- Limit żądań. 60 żądań na minutę na klucz (możliwy do zmiany per klucz). Odpowiedź 429 niesie
Retry-Afteroraz nagłówkiX-RateLimit-Limit / -Remaining / -Reset. - Odwołanie. Natychmiastowe, z konsoli. Rozpoznawanie odbywa się po skrócie: kluczy nie da się enumerować.
Trzy wywołania curl i masz obraz całości.
# Stan usługi + uwierzytelnienie kluczem
curl -s https://vigilae.org/api/v1/sante \
-H "Authorization: Bearer vgk_your_key"
# Dziennik monitoringu, od początku, stronami po 100
curl -s "https://vigilae.org/api/v1/evenements?depuisSeq=0&limite=100" \
-H "Authorization: Bearer vgk_your_key"
# Kwalifikacja zdarzenia 42 (uprawnienie zapisu)
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"}'Paginacja w jednej regule
Przekaż depuisSeq (0 przy pierwszym wywołaniu) i limite (maksymalnie 500): odpowiedź jest posortowana rosnąco po seq i zwraca prochainSeq, do przekazania bez zmian w kolejnym wywołaniu. Strona krótsza niż limite oznacza koniec dziennika — prochainSeq pozostaje wtedy stabilny i służy jako kursor odpytywania. Bez depuisSeq otrzymujesz widok „najnowsze najpierw”, ograniczony do 500.
Portfel odpytuje się na /api/v1/portefeuille/agregats — liczniki, jedna odpowiedź, bez paginacji.
Podpisane, ze znacznikiem czasu, dostarczane co najmniej raz.
Zamiast odpytywać dziennik, odbieraj go: Vigilae dostarcza zdarzenia na Twój URL, po kolei, w partiach po maksymalnie 100. Dostarczanie działa w trybie at-least-once — kursor przesuwa się tylko po Twoim 2xx, partia po partii — a idempotencja opiera się na seq: przetwórz każdą sekwencję dokładnie raz (#idempotence).
Weryfikacja podpisu
Każda dostawa niesie nagłówek x-vigilae-signature: t=<unix>,v1=HMAC-SHA256(secret, t + "." + body). Przelicz v1 z surowego otrzymanego body i odrzuć każdy znacznik czasu t starszy niż 5 min: to ochrona anty-replay. Podczas rotacji sekretu nagłówek niesie jedno v1 na każdy wciąż ważny sekret (24 h nakładania się): zaakceptuj, jeśli którekolwiek się zgadza.
// Node — weryfikacja podpisu (bez zależności)
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; // anty-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 — ta sama weryfikacja
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 # anty-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 FalsePrzejściowo: stary format sha256=HMAC(body) jest nadal emitowany w x-vigilae-signature-legacy dla już działających odbiorników; jego usunięcie planowane jest wraz z webhookami v2. Nowe odbiorniki weryfikują powyższy schemat ze znacznikiem czasu, nie stary.
Rotację wyzwala się z konsoli (POST /connect/webhook/rotation po stronie aplikacji): przez 24 h stary sekret nadal podpisuje — czas na wdrożenie nowego po Twojej stronie bez okna awarii.
Sandbox: na życzenie.
Każda klasa błędów API ma stały adres w katalogu błędów: #authentification, #scopes, #cloisonnement, #debit, #signature… Odpowiedzi błędów API będą wskazywać te kotwice.
API nie udostępnia ani zgłoszeń podejrzanych transakcji, ani dosłownych treści klienta — z samej konstrukcji (art. L.561-18 francuskiego CMF). API nie podejmuje żadnej decyzji w zakresie należytej staranności: udostępnia i kwalifikuje zdarzenia; decyduje osoba wykonująca zawód.