Siirry pääsisältöön
Certyneo
Kehittäjädokumentti

Webhooks vastaanottaa allekirjoitustapahtumat reaaliajassa

Aseta HTTPS-URL Certyneon paneelipaneelistallesi ja saat HMAC-SHA256-kirjatun POST-viestin, kun kirjekuoresi tapahtumat tapahtuvat: allekirjoitus, kieltäytyminen, päättyminen. 8 tapahtumaa tuettu, eksponentiaalinen uudelleenkokeilu kuudessa yrityksessä, 8 virkkeen koodin salauskäsittely.

< 5s

Tapahtuman jälkeinen keskimääräinen toimitusaika

5x

Yritykset epäonnistumisesta (kunnes ~ 9 tuntia on kulunut)

HMAC-SHA256

Jokaisen pyynnön allekirjoitusalgoritmi

Tapahtumakartta

Seuraavat 8 tapahtumaa kattavat Certyneon koko elinkaaren.

TapahtumaSe on aiheutunut
envelope.createdKirjaimessa on luotu kuori (UI, API tai malli) hyödyllinen CRM-sivuston synkronoimiseksi heti luodussa.
envelope.sentKirjaimeksianto lähetetään allekirjoittajalle (ensimmäinen lähetetty sähköposti).
envelope.completedKaikki allekirjoittajat ovat allekirjoittaneet. eIDAS-tyypillinen PDF ja auditointitulos ovat saatavilla `proof_pdf_url` osoitteessa.
envelope.declinedAllekirjoittaja on kieltäytynyt lähettämästä kirjekuorta.
envelope.voidedKirjaimeksiantaja peruutti kirjekuoren ennen kuin se oli allekirjoitettu.
envelope.expiredKirjeen voimassaolon päättymispäivä on kulunut ilman täydellistä allekirjoitusta.
recipient.signedYksittäinen allekirjoittaja on allekirjoittanut (mutta ei välttämättä kaikki).
recipient.viewedAllekirjoittaja avasi allekirjoituslinkin allekirjoittamatta vielä.

Palveluvaraston muoto

Kaikki tapahtumat jakavat saman JSON-tason kaavan: `event`, `envelope_id`, `occurred_at`, `data`.

{
  "event": "envelope.completed",
  "envelope_id": "env_01HG3K8X9Y2N4P5Q6R7S8T9V0W",
  "occurred_at": "2026-05-27T08:42:13.521Z",
  "data": {
    "title": "Contrat de prestation Acme Corp",
    "status": "completed",
    "created_at": "2026-05-24T14:12:00.000Z",
    "completed_at": "2026-05-27T08:42:13.000Z",
    "signers": [
      {
        "email": "client@acme.example",
        "name": "Alex Client",
        "signed_at": "2026-05-27T08:42:13.000Z",
        "method": "eidas_aes",
        "ip": "203.0.113.42"
      }
    ],
    "proof_pdf_url": "https://certyneo.com/api/envelopes/env_01HG.../proof.pdf"
  }
}

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 hakemus allekirjoitetaan webhookin salaisuudella (nähtävissä vain kerran laittamisen yhteydessä ja salaistuna silloin kun se on ladattu).<timestamp>V1 =<hex_hmac>Tarkista aina allekirjoitus ennen kuin käsittelet käyttökustannusta.

Node.js / TypeScript

import crypto from "node:crypto";

export function verifyCertyneoSignature(
  rawBody: string,
  signatureHeader: string,
  secret: string,
): boolean {
  // Header format: t=<timestamp>,v1=<hex_hmac>
  const parts = Object.fromEntries(
    signatureHeader.split(",").map((p) => p.split("=")),
  );
  const ts = parts.t;
  const sig = parts.v1;
  if (!ts || !sig) return false;

  // Reject events older than 5 minutes (replay protection).
  const age = Math.abs(Date.now() / 1000 - Number(ts));
  if (age > 300) return false;

  const expected = crypto
    .createHmac("sha256", secret)
    .update(`${ts}.${rawBody}`)
    .digest("hex");

  // timingSafeEqual to mitigate timing attacks.
  return crypto.timingSafeEqual(
    Buffer.from(expected, "hex"),
    Buffer.from(sig, "hex"),
  );
}

Python

import hashlib
import hmac
import time


def verify_certyneo_signature(
    raw_body: bytes, signature_header: str, secret: str
) -> bool:
    """Verify a Certyneo webhook signature.

    Header format: `t=<timestamp>,v1=<hex_hmac>`
    Rejects events older than 5 minutes (replay protection).
    """
    parts = dict(p.split("=") for p in signature_header.split(","))
    ts = parts.get("t")
    sig = parts.get("v1")
    if not ts or not sig:
        return False

    if abs(time.time() - int(ts)) > 300:
        return False

    expected = hmac.new(
        secret.encode("utf-8"),
        f"{ts}.{raw_body.decode('utf-8')}".encode("utf-8"),
        hashlib.sha256,
    ).hexdigest()

    return hmac.compare_digest(expected, sig)

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 päätepisteesi vastaa muuhun kuin HTTP 2xx (tilapäaika, 5xx, yhteys evätty), me äänestämme eksponentiaalisella varmuusvarmuudella. Yhteensä 6 yritystä ~9 tunnissa. Kuuden jälkeen tapahtuma merkitään `viisaksi ` verkkokeskustelupalveluasi ja varoitus sähköpostia lähetetään.

YritysKumoitu määräaikaAika on kulunut
#100
#2+ 1 min1 min
#3+ 5 min6 min
#4+ 30 min36 min
#5+ 2 h2h 36
#6+ 6 h8h 36

Jos haluat välittää epäonnistuneen tapahtuman manuaalisesti, webhookin ohjauspaneelissa on painike Toimitus jokaiselle epäonnistuneelle toimitukselle joka on käytettävissä 7 päivän ajan lopullisen epäonnistumisen jälkeen.

Testaus ilman oikeaa kirjekuorta

Lopputulos `/v1/webhooks/test` hyväksyy URL:n ja tapahtumatyypin ja POSTe:n fiktiivisen palkkion, joka on allekirjoitettu aivan kuin oikea.

# Trigger a test webhook to your endpoint
curl -X POST https://api.certyneo.com/v1/webhooks/test \
  -H "Authorization: Bearer $CERTYNEO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"event": "envelope.completed", "url": "https://your.app/webhooks/certyneo"}'

6 käytäntöä

  • Tarkista HMAC-signaatti ennen kehon lukemista käytä aikaa säästävää vertailua.
  • Käsitellä jokainen `envelope_id` × `event` vain kerran tallentamalla ID:t, jotka on jo nähty pohjaksi (sammutus voi palauttaa saman tapahtuman).
  • Vastaus HTTP 200:hen on oltava enintään 5 sekuntia, ja sitten asynkroninen (kiivu) käsittely.
  • HMAC-tarkastus epäonnistuu usein näkymättömän BOM:n tai valkoisen tilan vuoksi.
  • Liitä kuusi kuoppaa tapahtumien "epäonnistuneiden" tapahtumiin, jotta ne siirtyvät käsin, jos jokin on tapahtunut.
  • Suvaitse 5 minuutin viivästys `t=` ja vastaanottotunnin välillä sen jälkeen, hylkää, jotta toistoja ei tapahdu.

- Enemmänkin

Valmiina yhdistämään järjestelmänne?

Luoda ilmainen tili 2 minuutissa webhook-sovellus on saatavilla Starter-suunnitelmassa (ilmainen, 5 kirjekuorta/kuukausi).