Mur għall-kontenut prinċipali
Certyneo
Dokumentation tal-iżviluppatur

Webhooks tirċievi l-avvenimenti tas-sinjaġġ f'ħin reali

Ipprepara URL HTTPS fid-dashboard Certyneo tiegħek u tirċievi POST iffirmat HMAC-SHA256 malli jiġri xi ħaġa fuq il-kwestjonarju tiegħek: firma, rifjut, skadenza. 8 avvenimenti appoġġjati, reprova esponenzjali fuq 6 tentattivi, verifika kriptografika f'8 linji ta' kodiċi.

< 5s

Id-data medja ta' kunsinna wara l-avveniment

5x

Attentati jekk jonqsu (sa ~ 9h wara)

HMAC-SHA256

Algoritmu ta' firma għal kull talba

Katalgu tal-avvenimenti

L-8 avvenimenti hawn taħt jkopru ċ-ċiklu sħiħ tal-ħajja ta' kunsinna Certyneo. Ativa dawk li jinteressawk f'Settings → Webhooks, injora l-oħrajn is-sottoskrizzjoni hija granulari għal kull avveniment.

AvvenimentTqala
envelope.createdHuwa maħluq envelope (per UI, API jew template) utli biex tissinkronizza reġistrazzjoni fuq in-naħa CRM mill-ħolqien.
envelope.sentL-envelop jintbagħat lill-firmatarji (l-ewwel email mibgħuta). Dan jimmarka l-bidu taċ-ċiklu ta' firma attiva.
envelope.completedIl-PDF issiġillat eIDAS u l-awditjar trail huma disponibbli permezz ta' `proof_pdf_url` fil-payload.
envelope.declinedIr-raġuni għar-rifjut (jekk mogħtija mis-sinjur) tinsab f'data.decline_reason.
envelope.voidedL-envelop ġie kkanċellat mill-emittenti qabel ma l-firma tkun kompluta.
envelope.expiredId-data ta' skadenza tal-kwartina għaddiet mingħajr ma ġiet iffirmata b'mod sħiħ. Il-lista ta' min kien f'pożizzjoni li ma kienx ffirmat tinsab f'data.missing_signers.
recipient.signedF'dan il-każ, il-proċess ta' ċertifikazzjoni għandu jkun kompletament komplut.
recipient.viewedWieħed li ffirma l-ittra ħareġ il-link biex jiffirma mingħajr ma kien għadu ffirmat, utli għal riklami kummerċjali mmirati.

Format tal-payload

Il-ġrajjiet kollha jaqsmu l-istess skema ta' JSON top-level: `event`, `envelope_id`, `occurred_at`, `data`. Il-kontenut ta' `data` ivarja skont l-avveniment (kampijiet dokumentati għal kull avveniment fir-referenza API).

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

Il-payload huwa encoded UTF-8, mingħajr BOM. Is-sinja HMAC hija kkalkulata fuq il-body raw kif mibgħuta ma tbiddilx l-ispazji, l-ipparsing mill-ġdid JSON spiss jibdel l-ordni tal-ċwievet u jkisser il-verifika.

Iċċekkja l-HMAC

Kull talba hija ffirmata bis-sigriet webhook tiegħek (viżibbli darba biss meta tinħoloq fid-dashboard, imbagħad ikkodifikata meta tkun qed toqgħod).<timestamp>,v1=<hex_hmac>`. Dejjem iċċekkja s-sinjata qabel ma tipproċessa l-payload mingħajr dan il-pass, kull min jista' jforża avveniment u jsejjaħ l-endpoint tiegħek.

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)

Żball Komuni

Uża l-funzjoni time-safe (`crypto.timingSafeEqual` f'Node, `hmac.compare_digest` f'Python). inkella, id-differenza fil-ħin bejn żewġ sinjuri tiżvela l-kunċett lil attakkant paċenzjuż (timing attack).

Politika ta' ttestjar mill-ġdid

Jekk l-endpoint tiegħek jirrispondi xi ħaġa oħra ħlief HTTP 2xx (timeout, 5xx, connection refused), aħna nirringrazzjaw skont backoff esponenzjali. Total ta' 6 tentattivi f'~9 sigħat. Wara l-6, l-avveniment huwa mmarkat `failed` fid-dashboard webhook tiegħek u jintbagħat email ta' twissija.

AttentatId-data tal-għeluqIl-ħin li għadda
#100
#2+ 1 min1 min
#3+ 5 min6 min
#4+ 30 min36 min
#5+ 2 h2h 36
#6+ 6 h8h 36

Jekk trid tibgħat mill-ġdid event li ma jkunx sar, id-dashboard tal-webhook joffri buttuna Re-deliver fuq kull konsenja li ma tkunx saret disponibbli għal 7 ijiem wara li ma tkunx saret.

It-testijiet mingħajr ma tintbagħat enveloppa vera

L-endpoint `/v1/webhooks/test` jaċċetta URL u tip ta' avveniment, u POSTe payload fintiku ffirmat eżattament bħal reali. Ideali biex tivvalida l-maniġer tiegħek fl-integrazzjoni kontinwa jew waqt l-iżvilupp lokali (b'ngrok jew ekwivalenti).

# 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 Prattiki li Għandek Tsegwi

  • Iċċekkja s-sinja HMAC QABEL kull qari tal-ġisem uża tqabbil li jkun timing-safe.
  • Proċessa kull `envelope_id` × `event` darba biss billi taħżen l-IDs li diġà rajt fil-bażi (ir-ritrieħi jistgħu jerġgħu jagħtu l-istess avveniment).
  • Tweġiba HTTP 200 fi żmien 5 sekondi, u mbagħad ipproċessa bħala asinkronju (laħlaħ). Inkella inti se tkun timeout u jingħatalha bħala reattemp.
  • Il-logging tal-ġisem brut + is-sinjur sħiħ fid-debug il-verifika HMAC spiss tonqos fuq BOM jew spazju abjad inviżibbli.
  • Tgħaqqad dead-letter fil-kera fuq l-avvenimenti `failed` biex tibgħat manwalment f'każ ta' inċident fuq in-naħa tiegħek.
  • Tollera l-iskadenza ta' 5 minuti bejn `t=` u l-ħin tal-irċevuta lil hinn, irrifjuta biex jimblokka r-ripetizzjonijiet.

Biex tmur 'il quddiem

Lesti biex tgħaqqad is-sistemi tiegħek?

l-installazzjoni tal-webhook hija disponibbli mill-pjan Starter (b'xejn, 5 enveloppi/xahar).