Webhooks prijímajte podpísané udalosti v reálnom čase
Nakonfigurujte URL HTTPS na vašom dashboarde Certyneo a prijímajte POST podpísané HMAC-SHA256 hneď ako sa vyskytne udalosť vo vašich obálkach: podpis, odmietnutie, expirácia. Podporovaných 11 udalostí, 5 pokusov o doručenie s exponenciálnym spätným odlohom, kryptografická verifikácia za 8 riadkov kódu.
< 5s
Priemerné obdobie dodania po udalosti
5x
Pokusy o doručenie spolu, rozprestretí na približne 1 h 20
HMAC-SHA256
Algorytmus podpisu každej žiadosti
Katalog udalostí
12 nasledujúcich udalostí pokrýva celý životný cyklus obálky Certyneo. Aktivujte tie, ktoré vás zaujímajú v časti Nastavenia → Webhooky, ostatné ignorujte — odber je granulárny podľa udalosti.
| Podujatie | Vypúšťanie |
|---|---|
envelope.created | Vytvorí sa obal (v rámci UI, API alebo šablóny) užitočný na synchronizáciu záznamu na strane CRM hneď po jeho vytvorení. |
envelope.sent | Obálka je zaslaná signatárom (prvý odoslaný e-mail). |
envelope.completed | Všetci podepisujúci podpísali a zapečatený PDF eIDAS je skladovaný. Payload obsahuje signedDocumentUrl, odkaz s predsignáturou platný 7 dní; v opačnom prípade GET /v1/envelopes/id/signed-document a pešť auditu cez GET /v1/envelopes/id/audit-trail. |
envelope.declined | Podepisujúci odmietol obálku. Adresa odmieTajúceho je v `data.declinedBy` a dôvod, ak bol zadaný, v `data.reason`. |
envelope.voided | Obálka bola zrušená odosielateľom pred úplnou podpisom. |
envelope.expired | Dátum expirácie obálky uplynul bez úplného podpisu. Dotazujte sa GET /v1/envelopes/id, aby ste poznal chýbajúcich podepisujúcich. |
envelope.returned_to_sender | Podepisujúci vrátil obálku emitentovi na opravu bez jej odmietnutia. Dôvod je v `data.reason` a autor vrátenia v `data.returnedBy`. |
envelope.resubmitted | Emitent opravil a vrátil obálku, ktorá bola predtým vrátená. Označuje obnovenie cyklu podpisovania. |
recipient.signed | Jednotlivý podepisujúci podpísal (ale nie nutne všetci). Užitočné na sledovanie pokroku a postup na ďalší krok sekvenčného workflow. Pozor: zapečatený PDF v tejto fáze ešte neexistuje, dokonca ani pre posledného podepisujúceho — stiahnutie spustené tu vracia HTTP 409. Použite envelope.completed pre dokument. |
recipient.viewed | Jeden signatár otvoril podpisové prepojenie bez toho, aby to ešte podpísal, čo je užitočné pre cielené obchodné reklamu. |
recipient.approved | Schváliteľ overil obálku bez podpisu (workflow interného overenia). Adresa je v `data.approvedBy`. |
recipient.bounced | Poštovný server príjemcu natrvalo odmietol pozvánku alebo opakovaný pokus (neexistujúca poštová schránka, neaktívna doména). Príjemca sa zmení na stav BOUNCED a automatické opakované pokusy sa zastavenú. Adresa je v `data.recipientEmail`: opravte ju a potom znova odošlite obálku. |
recipient.signed neznamená "dokument je dostupný"
recipient.signed sa vydáva pre KAŽDÉHO podepisujúceho v momente, keď dokončí svoju signatúru — vrátane posledného, pred tým ako sa zapečatený PDF zostaví a skladuje. Stiahnutie spustené z tohto handlera teda vždy dostane HTTP 409 "Signed document not available until the envelope is COMPLETED". Toto nie je chyba: je to "ešte nie je pripravené". Prihláste sa na odber envelope.completed na získanie dokumentu a ponechajte recipient.signed na sledovanie pokroku (kto podpísal a kedy).
Formát užitočného nákladu
Všetky doručenia zdieľajú rovnaký schému JSON na najvyššej úrovni: `event`, `data` a `timestamp`. Názov udalosti sa tiež opakuje v hlavičke `X-Certyneo-Event`, čo umožňuje smerovanie ešte pred spracovaním tela. Obsah `data` sa líši podľa udalosti, ale vždy zostáva objektom plochých jednoduchých hodnôt — nikdy pole ani vnorený objekt. Tu je kompletné doručenie `envelope.completed`.
POST /webhooks/certyneo HTTP/1.1
Host: your.app
Content-Type: application/json
X-Certyneo-Event: envelope.completed
X-Certyneo-Delivery-Id: cm8f2h6a10004qr9k5p2wm3xt
X-Certyneo-Signature: 4f3d1c8b2a9e7f60d5c4b3a2918e7f6d5c4b3a2918e7f6d5c4b3a2918e7f6d5c{
"id": "cm8f2h6a10004qr9k5p2wm3xt",
"event": "envelope.completed",
"data": {
"envelopeId": "cm7x2k9p40001qz8h3f7bn2ld",
"sandbox": false,
"subject": "Contrat de prestation Acme Corp",
"status": "COMPLETED",
"signatureLevel": "ADVANCED",
"aesSignerCount": 2,
"completedAt": "2026-05-27T08:42:13.000Z",
"recipientCount": 2,
"recipients": [
{ "email": "alice@acme.com", "name": "Alice Martin", "role": "SIGNER", "status": "SIGNED" },
{ "email": "bob@acme.com", "name": "Bob Durand", "role": "SIGNER", "status": "SIGNED" }
],
"signedDocumentUrl": "https://storage.certyneo.com/signed/cm7x2k9p4.../contrat.pdf?X-Amz-Expires=604800&X-Amz-Signature=..."
},
"timestamp": "2026-05-27T08:42:13.521Z"
}signedDocumentUrl je odkaz s predsignáturou platný 7 dní od udalosti: vyhýba sa druhému autentifikovanému volaniu na získanie PDF. Je neprítomný — a nie null — ak pred-signatúra zlyhala, alebo na obálke QES dokončenej bez uloženého dokumentu; potom sa vráťte k GET /v1/envelopes/id/signed-document, ktorý zostáva zdrojom pravdy. Buďte si tiež vedomí manuálneho prehrania z dead-letter queue viac ako 7 dní po udalosti: odkaz v payloade je expirovaný, API endpoint nie.
Pôžitný náklad je kódovaný v UTF-8, bez BOM. HMAC podpis sa počíta na hrubom tele, ako je odoslaný nezmenujte medzery, re-parsing JSON často mení poradie kľúčov a porušuje overenie.
Overte podpis HMAC
Každá požiadavka je podpísaná s vašim webhookom tajomstva (zobrazené iba raz pri vytváraní odber). Signatúra sa prenáša v hlavičke `X-Certyneo-Signature`: je to HMAC-SHA256 nespracovaného tela požiadavky, zakódované v hexadecimálnom formáte, bez predpony ani časového pečiatka. VŽDY overujte signatúru pred spracovaním payloadu — bez tohto kroku môže ktokoľvek vymyslieť udalosť a zavolať váš endpoint.
Node.js / TypeScript
import crypto from "node:crypto";
export function verifyCertyneoSignature(
rawBody: string,
signatureHeader: string,
secret: string,
): boolean {
// X-Certyneo-Signature = HMAC-SHA256(secret, rawBody), hex-encoded.
const expected = crypto
.createHmac("sha256", secret)
.update(rawBody)
.digest("hex");
const received = Buffer.from(signatureHeader, "hex");
const computed = Buffer.from(expected, "hex");
// timingSafeEqual throws when the two buffers differ in length —
// a malformed header must return false, not crash the handler.
if (received.length !== computed.length) return false;
// timingSafeEqual to mitigate timing attacks.
return crypto.timingSafeEqual(computed, received);
}Python
import hashlib
import hmac
def verify_certyneo_signature(
raw_body: bytes, signature_header: str, secret: str
) -> bool:
"""Verify a Certyneo webhook signature.
`X-Certyneo-Signature` holds the hex-encoded HMAC-SHA256 of the
raw request body, computed with your webhook secret.
"""
expected = hmac.new(
secret.encode("utf-8"),
raw_body,
hashlib.sha256,
).hexdigest()
return hmac.compare_digest(expected, signature_header)Časté chyby
Použite funkciu time-safe (`crypto.timingSafeEqual` v Node, `hmac.compare_digest` v Pythone), inak časový rozdiel medzi dvoma podpismi postupne odhalí tajomstvo pacientovi (timing attack).
Politika retry
Ak váš endpoint trvá príliš dlho na odpoveď, odmietne pripojenie alebo vráti 5xx (alebo 429), opakujeme podľa exponenciálneho odsúvania: 5 pokusov spolu, počas približne 1 h 20. Po piatom pokuse sa udalosť pošle do frontu mŕtvych listov — môžete ju zobraziť a znova spustiť z vášho panela, ale už sa automaticky neopakuje. Explicitný refuz (401, 403, 404, 410, 422…) sa naopak nikdy neopakuje: odpoveď by sa nezmenilaúdalosť ide priamo do frontu mŕtvych listov.
| Skúšanie | Čas pred pokusom | Uplynulý čas od udalosti |
|---|---|---|
| #1 | 0 | 0 |
| #2 | + 1 min | 1 min |
| #3 | + 5 min | 6 min |
| #4 | + 15 min | 21 min |
| #5 | + 1 h | 1 h 21 |
Uvedené lehoty sú minimá: vyhľadávanie pokusov je regulované cronomerom, pokus preto môže začať o niečo neskôr ako teoretický čas. Opustené udalosti sú uvedené v sekcii Webhooks → Chyby, s tlačidlom ručného znovuspustenia bez limitu na dobu uchovávania. Endpoint, ktorý má päť definit ívnych zlyhaní — alebo ktorý odpovie 404 / 410 — sa automaticky deaktivuje a ste o tom informovaní e-mailom: znova ho aktivujte po oprave, počítadlo sa vynuluje (akákoľvek úspešná dodávka ho tiež vynuluje).
Testovanie bez zaslania skutočnej obálky
Najskôr vytvorte odber — odpoveď obsahuje `secret` potrebný na overenie HMAC, zobrazený len raz. Z časti Nastavenia → Webhooks tlačidlo „Testovať" následne pošle podpísaný POST presne ako skutočné doručenie a zobrazí vám surovu odpoveď vášho servera: je to najrýchlejší spôsob, ako overiť váš handler, lokálne cez ngrok alebo v nepretržitej integrácii.
# Create a subscription — "secret" is returned once, store it now.
curl -X POST https://api.certyneo.com/v1/webhooks \
-H "Authorization: Bearer $CERTYNEO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your.app/webhooks/certyneo",
"events": ["envelope.completed", "recipient.signed"]
}'URL musí byť verejne dostupná cez HTTPS: privátna adresa alebo localhost je odmietnutá ochranou SSRF v čase vytvorenia odberu.
Predplaty sú oddelené podľa prostredia, ako kľúče: webhook vytvorený s kľúčom sk_test_ prijíma iba udalosti z testovacích obálok, webhook vytvorený s kľúčom sk_live_ iba udalosti zo skutočných obálok. Testovacia obálka preto nikdy nedosiahne vašu produkčnú adresu URL a každá naplnená správa označuje „sandbox" (true alebo false).
6 postupov, ktoré je potrebné dodržiavať
- Zkontrolujte HMAC podpis PREČO čítať body použite časovo bezpečné porovnanie.
- Odstrániť duplikáty na základe hlavičky `X-Certyneo-Delivery-Id` (rovnaká ako `id` v tele) uložením už videných identifikátorov v databáze – opakovanie môže znova doručiť udalosť, ktorú ste už spracovali, ak sa vaša 2xx stratila, s rovnakým identifikátorom pri každom pokuse.
- Odpovedať HTTP 2xx do maximálne 10 sekúnd, potom spracovať asynchrónne (fronta). Pokiaľ nie, doručenie sa prerušuje a počíta sa ako zlyhanie.
- Logovať hrubé telo + úplný podpis v debugovaní HMAC overovanie často zlyhá na neviditeľnej BOM alebo bielom priestore.
- Sledujte stránku Webhooks → Chyby: ste informovaní e-mailom, ak je váš endpoint deaktivovaný, ale nie podľa udalosti — udalosť, ktorá vyčerpá svoje pokusy, musíte znova spustiť vy.
- Filtrovať udalosti pri prihlásení sa, nie v handleri, a zostať pod limitom 5 odberov na účet.
Nie ste povinní hostiť koncový bod na prijímanie týchto udalostí: konektor si vytvorí odber za vás a spustí tok priamo na udalosti obálky. Pozri Certyneo pre Power Automate a Microsoft 365.
Na ďalší krok
Ste pripravení zapojiť vaše systémy?
Webhooky a REST API sú zahrnuté od plánu Standard. Vytvorte si účet, vygenerujte kľúč `sk_test_` a pripojte váš koncový bod v sandboxe skôr, ako prejdete do produkcie.