Pojdite na glavno vsebino
Certyneo
Razvojni dokument

Webhooks prejemate dogodke v realnem času

V svojem nadzornem delu Certyneo nastavite HTTPS URL in prejmete podpisano POST, ki je HMAC-SHA256 takoj, ko se zgodi dogodek na vaših ovojnicah: podpis, zavrnitev, iztek. 8 podprtih dogodkov, eksponentni ponovni poskus na 6 poskusov, kriptografska preverjanje v 8 vrsticah kode.

< 5s

Povprečni čas dostave po dogodku

5x

Poskusi v primeru neuspeha (do ~ 9h kasneje)

HMAC-SHA256

Algoritem za podpis vsakega zahtevka

Katalog dogodkov

8 dogodkov spodaj pokriva celoten življenjski cikel Certyneo ovojnice.

DogodekIzbruh
envelope.createdUstvariti je treba povod (z UI, API ali predlogo) uporaben za sinhronizacijo registracije na strani CRM takoj po ustvarjanju.
envelope.sentOznaka za začetek cikla aktivnega podpisa.
envelope.completedVsi podpisniki so podpisali. eIDAS zapečateni PDF in sled avditiranja so na voljo preko `proof_pdf_url` v uporabnem breme.
envelope.declinedPodpisnik je zavrnil ovojnico. Razlog za zavrnitev (če ga podpiše podpisnik) je v `data.decline_reason`.
envelope.voidedPošiljatelj je razveljavil koverto, preden je bila podpisana.
envelope.expiredDatum izteka roka je potekel brez popolnega podpisa.
recipient.signedUporabno za zaporedne delovne tokove: sprožiti prehod na naslednjega podpisnika.
recipient.viewedPodpisnik je odprl podpisno povezavo, a še ni podpisal, kar je koristno za ciljno usmerjene trgovinske pobude.

Oblika uporabnega bremena

Vsi dogodki imajo enake top-level JSON sheme: `event`, `envelope_id`, `occurred_at`, `data`. Vsebina `data` se razlikuje glede na dogodek (okvirno dokumentirana polja v API referenci).

{
  "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"
  }
}

Podpis HMAC se izračuna na tistem prvotnem tkivu, kot je bil poslan.

Preverite podpis HMAC

Vsak zahtevek je podpisan z vašo webhook skrivnostjo (vidno samo enkrat, ko jo ustvarite v nadzorni plošči, nato šifrirano v mirovanju).<timestamp>,v1=<hex_hmac>Vedno preverite podpis, preden obdelate uporabni bremenik. Brez tega koraka lahko kdorkoli ponovi dogodek in pokliče vašo končno točko.

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)

Pogosta napaka

Ne uporabljajte `===` ali `==` za primerjavo pričakovanega in prejetega podpisa. Uporabite funkcijo time-safe (`crypto.timingSafeEqual` v Nodeju, `hmac.compare_digest` v Pythonu).

Politika ponovnega preskusa

Če vaša končna točka odgovori drugače kot HTTP 2xx (timeout, 5xx, connection refused), se odzovejo po eksponentnem back-offu. Šest poskusov v ~ 9 urah. Po šestih se dogodek označi `failed` v vaši webhook deski in pošlje opozorilni e-poštni naslov.

PoskusSkupni rokČas, ki je minil
#100
#2+ 1 min1 min
#3+ 5 min6 min
#4+ 30 min36 min
#5+ 2 h2h 36
#6+ 6 h8h 36

Če želite ročno posredovati neuspešni dogodek, ima webhook na napravo gumb Re-deliver na vsaki neuspešni dostavi na voljo 7 dni po dokončnem neuspehu.

Preizkus brez pošiljanja pravega kuverte

Končna točka `/v1/webhooks/test` sprejema URL in tip dogodka ter POŠTE fiktivni naložek, ki je podpisan točno kot pravi.

# 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 načel, ki jih je treba upoštevati

  • Preverite podpis HMAC PRED vsakim branjem telesa uporabite časovno varno primerjavo.
  • Obdelava vsakega `envelope_id` × `event` enkrat, tako da se shranijo ID, ki so bili že videni v bazi (izbira lahko ponovno prikaže isti dogodek).
  • Odgovorite HTTP 200 v največ 5 sekundah, nato pa obdelajte asinkronno (v vrsti).
  • Logiranje bruto telesa + polni podpis pri debugiranju preverjanje HMAC pogosto ne uspe na BOM ali nevidnem belem prostoru.
  • Vklopite Dead-letter v vrsto dogodkov, ki so se zgodili v primeru nesreče, da se v primeru nesreče v vašem servisu lahko vklopite ročno.
  • Dovoljenje za pet minutni odmik med `t=` in sprejemnim časom in pozneje, zavrnitev za blokiranje ponovitev.

Da bi šli dlje

Ste pripravljeni na povezovanje sistemov?

Ustvarite brezplačen račun v 2 minutah nastavitve webhooka so na voljo že na Starter načrtu (besplačno, 5 ovojnic/mesec).