Webhook'lar: Zapier, Make veya n8n'e bağlayın

Billfetch olaylarını Zapier, Make, n8n veya kendi sunucunuza gönderin: hangi olaylar var, her istek neye benziyor ve imza nasıl doğrulanır. · 6 dk okuma

Webhook, bir şey olduğunda (örneğin bir belgeyi onayladığınızda) Billfetch’in başka bir araca haber vermesini sağlar. Billfetch seçtiğiniz adrese kısa bir mesaj (JSON gövdeli bir HTTPS POST) gönderir. Zapier, Make ve n8n size bu adresi verir; böylece Billfetch’i kod yazmadan yüzlerce uygulamaya bağlayabilirsiniz.

Webhook ekleyin

  1. Zapier, Make veya n8n’de Webhooks by Zapier › Catch Hook, Custom webhook veya Webhook adlı bir tetikleyici oluşturun. Verdiği adresi kopyalayın.
  2. Billfetch’te Ayarlar’ı açın ve Entegrasyonlar altında Webhook’lar’ı seçin.
  3. Adresi yapıştırın. Adres https:// ile başlamalıdır.
  4. Gönderilecek olaylar altında bir veya daha fazla olay işaretleyin. En az bir olay gerekir.
  5. Webhook ekle’yi seçin.

Billfetch imza sırrını webhook’u ekledikten hemen sonra yalnız bir kez gösterir. Kopyala’yı seçin ve güvenli bir yerde saklayın. Yalnız Zapier veya Make kullanıyorsanız sırrı atlayabilirsiniz. İstekleri kendi sunucunuz alıyorsa, her isteğin gerçekten Billfetch’ten geldiğini sırla doğrulayın (aşağıya bakın).

Test gönderin

Bir webhook’un yanındaki Test gönder’i seçin. Billfetch hemen bir webhook.test olayı gönderir ve sonucu aynı satırda gösterir:

  • Teslim edildi · HTTP 200 · 312 ms: adres yanıt verdi, her şey çalışıyor. Zapier veya Make’te bu test isteğiyle sonraki adımları kurabilirsiniz.
  • Adres HTTP 404 yanıtı verdi (veya başka bir kod): adres yanıt verdi ama isteği reddetti. Adresin tam olduğunu ve Zap’in veya senaryonun açık olduğunu kontrol edin.
  • 10 saniye içinde yanıt gelmedi veya Adrese bağlanılamadı: adres yanlış ya da sunucu kapalı.
  • Adres özel ya da yerel bir ağı gösteriyor: adres herkese açık değil. Billfetch özel ağlara hiçbir zaman istek göndermez.

Her webhook için 10 dakikada en çok 5 test gönderebilirsiniz. Test gövdesi seçtiğiniz olayları ve her birinin bir örneğini içerir; böylece gerçek bir olay gelmeden alanları eşleyebilirsiniz.

Olaylar

OlayNe zaman gönderilir
document.receivedYeni bir belge geldiğinde: yükleme, e-posta, Telegram, bir bağlantı veya içe aktarma. Kasanızda zaten olan bir belgenin kopyası bu olayı tetiklemez.
document.approvedİncelemede bir belgeyi onayladığınızda.
export.completedBir muhasebeci paketi üretildiğinde.
missing.summaryGünde bir kez (07:00 UTC): bu ay hâlâ eksik olan kalemlerin sayısı.
webhook.testYalnız Test gönder’i seçtiğinizde.

Bir istek neye benzer

Her istek Content-Type: application/json ile bir POST’tur ve şu başlıkları taşır:

BaşlıkAnlamı
Billfetch-EventOlay türü, örneğin document.approved.
Billfetch-DeliveryBu teslimatın benzersiz kimliği. Teslimat yeniden denendiğinde değişmez; tekrarları bununla ayıklayabilirsiniz.
Billfetch-Signaturet=<unix zamanı>,v1=<imza>. “İmzayı doğrulayın” bölümüne bakın.
User-AgentBillfetch-Webhooks/1.0

Gövde her zaman aynı zarftadır. id olay kimliğidir (bu olayı alan her webhook’ta aynıdır), data olaya göre değişir:

{
  "id": "3f0b6a52-7a7e-4c1d-9f8e-0f3c2b1a9d10",
  "type": "document.approved",
  "occurredAt": "2026-10-17T09:30:00+00:00",
  "tenantId": "8d2c4e1a-0b5f-4a7e-9c3d-2e1f0a9b8c7d",
  "data": {
    "documentId": "00000000-0000-0000-0000-000000000001",
    "ledgerItemId": "00000000-0000-0000-0000-000000000002",
    "entityId": "00000000-0000-0000-0000-000000000003",
    "categoryId": "00000000-0000-0000-0000-000000000004",
    "supplier": "Example Supplies Ltd",
    "invoiceNumber": "INV-1042",
    "issueDate": "2026-10-15",
    "currency": "GBP",
    "gross": 120.00,
    "tax": 20.00
  }
}

Diğer olayların data alanı:

// document.received
{ "documentId": "…", "filename": "invoice-1042.pdf", "source": "Upload", "receivedAt": "2026-10-17T09:30:00+00:00",
  "mime": "application/pdf", "size": 48213, "entityId": null }

// export.completed
{ "exportJobId": "…", "entityId": "…", "from": "2026-09-01T00:00:00+00:00", "to": "2026-09-30T23:59:59+00:00",
  "profile": "xero_csv", "mode": "full", "documents": 42, "contentHash": "9f86d0…" }

// missing.summary — Eksikler listesinin bölüm başına sayıları
{ "period": "2026-10", "sections": { "a": 3, "b": 1, "c": 0 } }

source şunlardan biridir: Upload, Imap (e-posta), Connector, CompaniesHouse, Telegram, Migration (Dext/AutoEntry içe aktarma), Accountant veya AccountantUnverified. Tutarlar sayıdır, tarihler ISO 8601 biçimindedir. Zamanla yeni alanlar eklenebilir; tanımadığınız alanları yok sayın.

İmzayı doğrulayın

İstekleri kendi sunucunuz alıyorsa bunu yapın. İsteğin Billfetch’ten geldiğini ve değiştirilmediğini kanıtlar.

  1. Billfetch-Signature başlığını okuyun ve t (Unix zaman damgası) ile v1’e (imza) ayırın.
  2. t’yi, bir noktayı ve istek gövdesini ham hâliyle, geldiği gibi birleştirin; örneğin 1760693400.{"id":…}. JSON’u önce ayrıştırıp yeniden yazmayın.
  3. Bu metnin HMAC-SHA256 değerini, anahtar olarak imza sırrının tamamını (whsec_ öneki dahil) kullanarak hesaplayın ve küçük harfli onaltılık (hex) yazın.
  4. Sonucu v1 ile sabit süreli bir karşılaştırmayla karşılaştırın. Farklıysa veya t sunucunuzun saatinden 5 dakikadan fazla uzaksa isteği reddedin.

Node.js:

import crypto from 'node:crypto'

// rawBody: gövde geldiği gibi (string ya da Buffer), yeniden yazılmış JSON değil.
export function verifyBillfetch(rawBody, header, secret, toleranceSeconds = 300) {
  const parts = Object.fromEntries(header.split(',').map((p) => p.split('=')))
  const t = Number(parts.t)
  if (!t || Math.abs(Date.now() / 1000 - t) > toleranceSeconds) return false
  const expected = crypto.createHmac('sha256', secret).update(`${t}.${rawBody}`).digest()
  const given = Buffer.from(parts.v1 ?? '', 'hex')
  return given.length === expected.length && crypto.timingSafeEqual(given, expected)
}

Python:

import hashlib
import hmac
import time


def verify_billfetch(raw_body: bytes, header: str, secret: str, tolerance: int = 300) -> bool:
    parts = dict(p.split("=", 1) for p in header.split(","))
    t = int(parts.get("t", "0"))
    if abs(time.time() - t) > tolerance:
        return False
    expected = hmac.new(secret.encode(), f"{t}.".encode() + raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, parts.get("v1", ""))

Yeniden denemeler ve zaman aşımı

  • Billfetch yanıt için en çok 10 saniye bekler. Her 2xx durum kodu teslim edildi sayılır. Yönlendirmeler izlenmez.
  • Teslimat başarısız olursa Billfetch 1 dakika, 5 dakika, 30 dakika, 2 saat ve 12 saat sonra yeniden dener: yaklaşık 15 saatte toplam 6 deneme. Sonra teslimat Başarısız olarak işaretlenir.
  • Test olayları bir kez gönderilir, yeniden denenmez.
  • Teslimatlar birden fazla kez veya farklı sırayla gelebilir. Tekrarları Billfetch-Delivery veya olay id’si ile ayıklayın.
  • Webhook kartındaki Son teslimatlar son teslimatları durumları ve son HTTP koduyla gösterir.

Sırrı güvende tutun

  • Sır sızdıysa veya kaybettiyseniz webhook’un yanındaki Yeni sır’ı seçip onaylayın. Eski sır hemen geçersiz olur; yenisini hemen aracınıza yapıştırın.
  • Kaldır, bekleyen yeniden denemeler dahil o adrese tüm gönderimleri durdurur.
  • Billfetch yalnız herkese açık https:// adreslerine gönderir. Düz http, localhost ve özel ağ adresleri reddedilir.

İlgili

Hâlâ yardıma mı ihtiyacınız var? Destek ekibine ulaşın veya kendiniz deneyin — kaydolmak bir dakika sürer.