Pāriet uz galveno saturu
Certyneo
Izstrādātāja dokumentācija

Webhooks saņemties autorei aktuālos notikumus

Sekojiet HTTPS URL konfigurācijai Certyneo vadības panelī un saņemsiet HMAC-SHA256 parakstītu POST, kad vien kāds notikums notiek jūsu aploksnēs: paraksts, atteikums, termiņš.

< 5s

Vidējais piegādes laiks pēc notikuma

5x

Piegādes mēģinājumi, ja nav panākti panākumi (līdz ~ 9h vēlāk)

HMAC-SHA256

Katras pieprasījuma parakstīšanas algoritms

Rīcības katalogs

8 turpmāk minētie notikumi aptver visas Certyneo apvalka dzīves ciklus.

IzskatsIzslēgums
envelope.createdIzveido apvalku (atkarībā no UI, API vai templates) kas noder sinhronizēt ierakstus CRM pusē, kad to izveido.
envelope.sentApakšbukls tiek nosūtīts parakstītājiem (pirmais nosūtīts e-pasts).
envelope.completedVisi parakstītāji ir parakstījušies. eIDAS piestiprināta PDF un audita ceļā ir pieejami payloadā.
envelope.declinedSazinieties ar ārstu, lai pārliecinātos, ka jūsu ārstēšanas kurss ir piemērots.
envelope.voidedIzdevējs ir anulējis aploksni pirms pilnīgas parakstīšanas.
envelope.expiredPārbaudes datums ir pagājis bez pilnīgas paraksta.
recipient.signedViens parakstītājs ir parakstījis (bet ne visi).
recipient.viewedSazinieties ar mums, lai uzzinātu, kas notiek.

Nedaudz vairāk

Visas lietas ir līdzīgas JSON top-level formātā: `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 signātu aprēķina uz brūnajiem korpusa datiem, kā nosūtīts.

Pārbaudiet HMAC parakstu

Katru pieprasījumu paraksta ar jūsu webhook noslēpumu (izskatāms tikai vienu reizi, kad izveidojiet to, un pēc tam kodēts, kad esat atstājuši).<timestamp>,v1=<hex_hmac>Vispirms pārbaudiet parakstu, pirms apstrādājat slodzi. Bez šī posma ikviens var izdomāt notikumu un izsaukt jūsu galamērķi.

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)

Bieži pieļauta kļūda

Nelietojiet `===` vai `==`, lai salīdzinātu gaidīto un saņemto parakstu. Izmantojiet funkciju "timing-safe" (`crypto.timingSafeEqual` Node, `hmac.compare_digest` Python).

Atjaunināšanas politika

Ja jūsu galamērķis atbild uz kaut ko citu, nevis HTTP 2xx (timeout, 5xx, connection refused), mēs izsakām pēc eksponenciālā back-off. Kopumā 6 mēģinājumi ~9 stundās. Pēc 6 notikums tiek atzīmēts kā `failed` jūsu webhook vadības pulkstenī un tiek nosūtīts brīdinājuma e-pasts.

PētījumsKopējais termiņšIzgājis laiks
#100
#2+ 1 min1 min
#3+ 5 min6 min
#4+ 30 min36 min
#5+ 2 h2h 36
#6+ 6 h8h 36

Ja vēlaties manuāli pārsūtīt neizdotos notikumus, webhook vadības pults piedāvā Atdodiet uz katru neizdoto piegādi 7 dienas pēc galīgās neizdodas.

Testēšana bez īsta aploksnes nosūtīšanas

Vislabāk ir izmantot šo metodi, lai pārbaudītu, vai jūsu lietotājs ir izpildījis visus nepieciešamos nosacījumus.

# 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 prakse, kas jāpiemēro

  • Pārbaudiet HMAC parakstu ANEISKĀT visu ķermeņa skaitīšanu izmantojiet laiku drošus salīdzinājumus.
  • Izstrādājiet katru `envelope_id` × `event` tikai vienu reizi, uzglabājot ID, kas jau redzēti bāzē (atgriezeniski var atdot to pašu notikumu).
  • Atbilde HTTP 200 5 sekundēs, tad apstrāde asinkronā (saukā).
  • Brūna ķermeņa reģistrācija + pilnīga paraksta debugēšana HMAC pārbaude bieži neizdodas uz neredzamu BOM vai baltumu.
  • Pievienojiet dead-letter rindas uz notikumiem `failed` manuāli pārraidīt gadījumā, ja notikums jūsu dienests.
  • Atļaut 5 minūšu atkāpi no `t=` līdz saņemšanas laikam, atstāt, lai bloķētu pārraidījumus.

Lai sasniegtu vēl lielāku mērķi

Gatavi pieslēgt sistēmas?

Grāmatas izveidošana bez maksas 2 minūtēs webhook konfigurācija ir pieejama jau Starter plānā (bezdarbīgi, 5 aploksnes mēnesī).