Ana içeriğe git
Certyneo
Geliştirici belgeleri

Webhooks gerçek zamanlı imza olaylarını alın

Certyneo panolarınızda bir HTTPS URL ayarlayın ve zarflarınızda bir olay olduğunda HMAC-SHA256 imzalı bir POST alın: imza, reddedilme, sona erme. 8 olay desteklenir, 6 deneme ile katlanarak tekrar denenebilir, 8 satırlık şifre doğrulama.

< 5s

Olay sonrası ortalama teslim süresi

5x

Başarısızlık denemeleri ( ~ 9 saat sonra)

HMAC-SHA256

Her talebin imzası algoritması

Olay Kataloğu

Aşağıdaki 8 olay, bir Certyneo zarfının tüm yaşam döngüsünü kapsar. Seçenekler → Webhooks'ta ilgilendiğiniz olayları etkinleştirin, diğerlerini görmezden gelin abonelik olay başına granülerdir.

OlayÇıkış
envelope.createdBir zarf oluşturulur (UI, API veya şablon tarafından) CRM tarafında bir kayıt oluşturulduğunda senkronize etmek için kullanılır.
envelope.sentZarf, imzalayanlara gönderilir (ilk e-posta gönderilmektedir).
envelope.completedTüm imzacılar imzaladı. eIDAS mühürlü PDF ve iz denetimi payload'da `proof_pdf_url` üzerinden mevcuttur.
envelope.declinedİmzacı, mührü reddetti.Rezim sebebi (imzacı tarafından verildiğinde) `data.decline_reason`'da yer almaktadır.
envelope.voidedBütçe, göndericiden imzalandırılmadan önce iptal edildi.
envelope.expiredEnvantopun son kullanma tarihi tam olarak imzalanmadan geçti. Kayıp imzalayanların listesi `data.missing_signers`'da.
recipient.signedBireysel bir imzacı imzaladı (ama hepsi değil). Sıralı iş akışları için yararlı: bir sonraki imzacıya geçiş yaptırmak.
recipient.viewedBir imzacı imzalama bağlantısını henüz imzalamadan açtı.

Uygulanabilir yükü biçimi

Tüm olaylar aynı üst seviye JSON şemasını paylaşır: `event`, `envelope_id`, `occurred_at`, `data`. `data` içeriği olay başına göre değişir (API referansındaki olay başına belgelenen alanlar). İşte tam bir örnek `envelope.completed`.

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

Payload UTF-8 kodlanmıştır, BOM bulunmamaktadır. HMAC imzası gönderildiği gibi gövdeye hesaplanır boşlukları değiştirmeyin, JSON yeniden ayrıştırılması genellikle anahtarların sırasını değiştirir ve doğrulamaları bozar.

HMAC imzasını kontrol et.

Her istek webhook gizinizle imzalanacak (dashboard'da oluşturulduğunda bir kez görünür, sonra dinlenirken şifrelenmiş olacak). İmza `Certyneo-Signature` başlığında `t= biçiminde iletilecek<timestamp>V1=<hex_hmac>Payload'u işlemeden önce her zaman imza kontrol edin. Bu adım olmadan, herkes bir olayı sahteleyip son noktanızı arayabilir.

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)

Sıkça yapılan hatalar

Beklenen imzayı alınan imzaya karşılaştırmak için `===` veya `==` kullanmayın. Zamanlama güvenli bir işlev kullanın (`crypto.timingSafeEqual` Node'de, `hmac.compare_digest` Python'da). Aksi takdirde, iki imza arasındaki karşılaştırma zaman farkı sırrı yavaş yavaş hasta bir saldırganın (zamanlama saldırısı) farkına neden olur.

Tekrar deneme politikası

Eğer uç noktanız HTTP 2xx (timeout, 5xx, connection refused) dışında bir şey yanıtlarsa, katlanarak yedekleme yapıyoruz. Toplamda ~9 saat içinde 6 girişim. 6'sının ardından olay webhook panolarınızda `failed` olarak işaretlenir ve uyarı e-postası gönderilir.

DenemeToplam süreGeçmiş zaman
#100
#2+ 1 min1 min
#3+ 5 min6 min
#4+ 30 min36 min
#5+ 2 h2h 36
#6+ 6 h8h 36

Eğer başarısız bir olayı elle iletmek istiyorsanız, webhook panoları başarısız olan her teslimat için bir Tekrar teslimat düğmesi sunar.

Gerçek zarf göndermeden test etmek

`/v1/webhooks/test` son noktası bir URL ve bir olay türünü kabul eder ve gerçek gibi tam olarak imzalanan hayali bir payload gönderir.

# 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 Uyumlu Uygulamalar

  • HMAC imzasını BİR BİR BİR BÜR BÜR BÜR BÜR BÜR BÜR BÜR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR BİR
  • Her `envelope_id` × `event`'i, bazda zaten görülen ID'leri saklayarak sadece bir kez işleyin (dönüşümler aynı olayı tekrar sunabilir).
  • HTTP 200'e en fazla 5 saniye içinde cevap verin, sonra asynchronous olarak işleyin (kuyruk). Aksi takdirde zaman aşımına uğrayacaksınız ve tekrar deneme olarak sayılacaksınız.
  • Kötü vücut + tam imzanın depoglanması HMAC doğrulama genellikle görünmez bir BOM veya beyaz alan üzerinde başarısız olur.
  • Default. olaylar için bir dead-letter kuyruğu takın.
  • `t=` ile sonrası zaman aralığı arasında 5 dakika geçişe izin verin, tekrarları engellemek için reddedin.

Daha Fazla

Sistemlerinizi bağlamaya hazır mısınız?

Ücretsiz bir hesap oluştur 2 dakikada webhook kurulumları Starter planından (ücretsiz, ayda 5 zarf) mevcuttur.