Webhooks vastaanottaa allekirjoitustapahtumat reaaliajassa
Määritä HTTPS-URL Certyneo-hallintapaneelissasi ja vastaanota HMAC-SHA256-allekirjoitettu POST aina, kun kirjekuorissasi tapahtuu jotakin: allekirjoitus, kieltäytyminen, vanhentuminen. 11 tuettua tapahtumaa, 5 toimintoyritystä eksponentiaalisella viiveellä, salausvarmennus 8 koodirivillä.
< 5s
Tapahtuman jälkeinen keskimääräinen toimitusaika
5x
Toimintoyritykset yhteensä, jaettu noin 1 h 20 min ajalle
HMAC-SHA256
Jokaisen pyynnön allekirjoitusalgoritmi
Tapahtumakartta
12 alla olevaa tapahtumaa kattaa Certyneo-kirjekuoren koko elinkaaren. Ota käyttöön ne, jotka kiinnostavat sinua kohdassa Asetukset → Webhookit, jätä muut huomioimatta — tilaus on jäsennelty tapahtumittain.
| Tapahtuma | Se on aiheutunut |
|---|---|
envelope.created | Kirjaimessa on luotu kuori (UI, API tai malli) hyödyllinen CRM-sivuston synkronoimiseksi heti luodussa. |
envelope.sent | Kirjaimeksianto lähetetään allekirjoittajalle (ensimmäinen lähetetty sähköposti). |
envelope.completed | Kaikki allekirjoittajat ovat allekirjoittaneet ja eIDAS-sinetöity PDF on tallennettu. Payload sisältää signedDocumentUrl-linkin, ennakkoon allekirjoitetun linkin, joka on voimassa 7 päivää; muussa tapauksessa käytä GET /v1/envelopes/id/signed-document ja tarkastuspolku GET /v1/envelopes/id/audit-trail-kautta. |
envelope.declined | Allekirjoittaja kieltäytyi kirjekuoresta. Kieltäytyjän osoite on kohdassa `data.declinedBy` ja perustelu, jos se on syötetty, kohdassa `data.reason`. |
envelope.voided | Kirjaimeksiantaja peruutti kirjekuoren ennen kuin se oli allekirjoitettu. |
envelope.expired | Kirjekuoren vanhentumispäivä on ohitettu ilman täydellistä allekirjoitusta. Kysy GET /v1/envelopes/id nähdäksesi puuttuvat allekirjoittajat. |
envelope.returned_to_sender | Allekirjoittaja palautti kirjekuoren lähettäjälle korjausta varten ilman sen kieltäytymistä. Perustelu on kohdassa `data.reason` ja palauttajan tekijä kohdassa `data.returnedBy`. |
envelope.resubmitted | Lähettäjä korjasi ja palautti aiemmin palautetun kirjekuoren. Merkitsee allekirjoituskierron jatkamista. |
recipient.signed | Yksittäinen allekirjoittaja on allekirjoittanut (mutta ei välttämättä kaikki). Hyödyllinen edistymisen seurantaan ja seuraavan vaiheen ketjuttamiseen peräkkäisessä työnkulussa. Varoitus: allekirjoitettua PDF:ää ei ole vielä olemassa tässä vaiheessa, jopa viimeiselle allekirjoittajalle — täältä käynnistetty lataus palauttaa HTTP 409:n. Käytä envelope.completed-tapahtumaa asiakirjaa varten. |
recipient.viewed | Allekirjoittaja avasi allekirjoituslinkin allekirjoittamatta vielä. |
recipient.approved | Hyväksyjä hyväksyi kirjekuoren ilman allekirjoituksen liittämistä (sisäisen vahvistuksen työnkulku). Osoite on kohdassa `data.approvedBy`. |
recipient.bounced | Vastaanottajan sähköpostipalvelin hylkäsi kutsu tai uudelleenyrityksen lopullisesti (olematon postilaatikko, kuollut verkkotunnus). Vastaanottaja siirtyy BOUNCED-tilaan ja automaattiset uudelleenyritykset pysähtyvät. Osoite on kohdassa `data.recipientEmail`: korjaa se ja lähetä kirjekuori uudelleen. |
recipient.signed ei tarkoita « asiakirja saatavilla »
recipient.signed lähetetään JOKAISELLE allekirjoittajalle, kun hän lopettaa allekirjoituksensa — myös viimeiselle, ennen kuin sinetöity PDF on koottu ja tallennettu. Tältä käsittelijältä käynnistetty lataus saa siis aina HTTP 409:n « Signed document not available until the envelope is COMPLETED ». Tämä ei ole virhe: se on « ei vielä valmis ». Tilaa envelope.completed asiakirjan hakemiseksi ja pidä recipient.signed edistymisen seurantaan (kuka allekirjoitti ja milloin).
Palveluvaraston muoto
Kaikilla toiminnoilla on sama ylin JSON-kaavio: `event`, `data` ja `timestamp`. Tapahtuman nimi toistetaan myös `X-Certyneo-Event`-otsikossa, mikä mahdollistaa reitityksen jo ennen tekstin jäsentämistä. `data`-sisältö vaihtelee tapahtuman mukaan, mutta on aina litteä objekti yksinkertaisista arvoista — ei koskaan taulukkoa eikä sisäkkäistä objektia. Tässä on täydellinen `envelope.completed`-toiminto.
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 on ennalta allekirjoitettu linkki, joka on voimassa 7 päivää tapahtumasta lähtien: se välttää toisen todentavan puhelun PDF:n hakemiseksi. Se puuttuu — eikä ole null — jos ennakkoallekirjoitus epäonnistui tai QES-kirjekuoressa, joka on täytetty ilman tallennettua asiakirjaa; palaa siihen GET /v1/envelopes/id/signed-document, joka on totuuden lähde. Huomio myös manuaalisesta uudelleenyrityksen takia dead-letter jonosta yli 7 päivää tapahtuman jälkeen: payload-linkki on vanhentunut, API-päätepiste ei.
HMAC-signaatti lasketaan raaka-ainetta vastaan älä muuta väliä, JSON-re-parsing muuttaa usein avainten järjestystä ja rikkoo tarkistuksen.
Tarkista HMAC-sääntö
Jokainen pyyntö allekirjoitetaan webhook-salaisuudellasi (näytetään vain kerran tilauksen luomisen yhteydessä). Allekirjoitus välitetään `X-Certyneo-Signature` -otsikossa: se on pyynnön raakarunko HMAC-SHA256, koodattu heksadesimaalilla, ilman etuliitettä tai aikaleimaa. Tarkista AINA allekirjoitus ennen payload-käsittelyä — ilman tätä vaihetta kuka tahansa voi väärentää tapahtuman ja kutsua päätepistettäsi.
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)Yleinen virhe
Älä käytä `===` tai `==` vertaamaan odotettua ja vastaanotettua allekirjoitusta. Käytä aikavarmaa toimintoa (`crypto.timingSafeEqual` Node, `hmac.compare_digest` Python).
Uudelleenkäsittelypolitiikka
Jos endpoint-palvelusi vastaa liian hitaasti, kieltää yhteyden tai palauttaa 5xx-virheen (tai 429-koodin), yritämme uudelleen eksponentiaalisella backoff-strategialla: yhteensä 5 yritystä noin 1 h 20 minuutissa. Viidennen yrityksen jälkeen tapahtuma siirtyy dead-letter jonoon — se on nähtävissä ja toistettavissa kojelaustasi, mutta sitä ei enää uudelleen yritetä automaattisesti. Eksplisiittinen kieltäytyminen (401, 403, 404, 410, 422 jne.) ei sitä vastoin ole koskaan uudelleen yritetty: vastaus ei muuttuisi, tapahtuma siirtyy suoraan dead-letter jonoon.
| Yritys | Kello ennen yritystä | Aikaa kulunut sitten tapahtumasta |
|---|---|---|
| #1 | 0 | 0 |
| #2 | + 1 min | 1 min |
| #3 | + 5 min | 6 min |
| #4 | + 15 min | 21 min |
| #5 | + 1 h | 1 h 21 |
Ilmoitetut aikarajat ovat minimeja: retry-skannaus on cron-aikaistettu, joten yritys voi lähteä hieman teoreetista aikaa myöhemmin. Hylätyt tapahtumat on lueteltu kohdassa Webhooks → Virheet, joissa on manuaalisen toiston painike ja rajoittamaton säilytysaika. Endpoint, joka epäonnistuu viisi kertaa peräkkäin – tai vastaa 404/410 – poistetaan käytöstä automaattisesti ja saat siitä ilmoituksen sähköpostilla: aktivoi se uudelleen korjaamisen jälkeen, laskuri nollautuu (mikä tahansa onnistunut toimitus nollaa sen myös).
Testaus ilman oikeaa kirjekuorta
Luo ensin tilaus — vastaus sisältää `secret`-avain, joka on tarpeen HMAC-verifiointiin ja näytetään vain kerran. Asetuksista → Webhooks -painikkeesta « Testaa » lähettää POST-pyynnön, joka on allekirjoitettu täsmälleen kuin todellinen toimitus, ja näyttää palvelimesi raakavastauksen: se on nopein tapa vahvistaa käsittelijäsi, paikallisesti ngrok:n kautta tai jatkuvassa integraatiossa.
# 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:n on oltava julkisesti saavutettavissa HTTPS:n kautta: yksityinen osoite tai localhost hylätään SSRF-suojauksella tilauksen luomisen yhteydessä.
Tilaukset erotetaan ympäristöittäin kuten avaimet: sk_test_-avaimella luotu webhook vastaanottaa vain testikuorien tapahtumia, sk_live_-avaimella luotu webhook vain todellisten kirjekuorien tapahtumia. Testikuori ei siis koskaan saavuta tuotanto-URL-osoitettasi, ja jokainen hyötykuorma ilmoittaa "sandbox" (true tai false).
6 käytäntöä
- Tarkista HMAC-signaatti ennen kehon lukemista käytä aikaa säästävää vertailua.
- Poista duplikaatit `X-Certyneo-Delivery-Id` -otsikon perusteella (sama kuin `id` rungossa) tallentamalla jo nähdyt tunnisteet tietokantaan — uudelleenyritys voi toimittaa tapahtuman, jonka olet jo käsitellyt, jos 2xx hävisi, samalla tunnuksella joka yrityksellä.
- Vastaa HTTP 2xx enintään 10 sekunnissa, sitten käsittele asynkronisesti (jono). Tämän jälkeen toimitus katkeaa ja lasketaan virheeksi.
- HMAC-tarkastus epäonnistuu usein näkymättömän BOM:n tai valkoisen tilan vuoksi.
- Valvo Webhooks → Virheet -sivua: sinut ilmoitetaan sähköpostilla, jos endpoint poistetaan käytöstä, mutta ei tapahtuma kerrallaan – tapahtuma, joka kuluttaa yritykset loppuun, sinun on mentävä toistamaan se itse.
- Suodata tapahtumat tilauksen yhteydessä eikä käsittelijässäsi, ja pysy 5 tilauksen rajalla tiliä kohti.
Et ole velvollinen isännöimään päätepistettä näiden tapahtumien vastaanottamiseksi: liitin asettaa tilauksen puolestasi ja käynnistää työnkulun suoraan kirjekuoritapahtumaan. Katso Certyneo Power Automatea ja Microsoft 365:tä varten.
Lue lisää
Valmiina yhdistämään järjestelmänne?
Webhookit ja REST-API sisältyvät Standard-planista lähtien. Luo tilisi, generoi `sk_test_` -avain ja yhdistä päätepistesi hiekkalaatikossa ennen siirtymistä tuotantoon.