B2B Worker
B2B Worker Docs

Geliştiriciler: Kendi sunucunu tetikle

Akışlardaki HTTP isteği adımı, akış çalışırken kendi API'nize veya sunucunuza istek atar. Yanıtı akışta kullanabilir, hata olursa tekrar deneyebilir veya uzun süren işlerde sizden geri çağrı (callback) bekleyebilir.

Tipik kullanımlar:

  • Partner onaylayınca kendi sisteminize POST /orders/{{order_id}}/confirm atmak
  • Deploy, rapor veya senkronizasyon job'u başlatmak
  • Slack, n8n, Zapier gibi bir webhook'u çağırmak
  • GET /customers/{{phone}} ile veri çekip yanıttaki bir alana göre dallanmak

Adımı eklemek

Akış editöründe + Adım ekle → HTTP isteği seçin. Başlarken üç yol vardır: Elle oluştur, cURL yapıştır veya OpenAPI (yakında). Editör üç bölümden oluşur.

1. Nereye ve ne yapmak istiyorsun?

BağlantıNe seçilir
Hazır entegrasyonlar (B2B CRM, Bitrix24)İşlem (Yeni kayıt oluştur, Kayıt getir, Kaydı güncelle, Özel istek), kayıt türü ve gerekiyorsa kayıt ID. Adres ve kimlik bilgisi entegrasyon ayarlarından otomatik gelir.
BağlantılarımKendi API'niz. İşlem method'u belirler (Oluştur → POST, Getir → GET, Güncelle → PATCH, Sil → DELETE); siz yalnızca /customers/{{customer_id}} gibi yolu yazarsınız.
Tek seferlik URLKimlik doğrulaması gerekmeyen adresler için method + tam URL.

2. Erişim ve gönderilecek veriler

Kimlik doğrulama seçilen bağlantıdan gelir; adımda token saklanmaz. Gönderilecek veriler Alan / Değer tablosuyla eşlenir:

AlanDeğer
full_nameDeğişken: Tetikleyici → Ad Soyad
phoneDeğişken: Tetikleyici → Telefon
sourceSabit: whatsapp
  • Hazır entegrasyonlarda alan listesi CRM şemasından gelir; zorunlu alanlar başta ve * ile işaretlidir, eksikse uyarı görünür.
  • Kendi API'nizde alan adını siz yazarsınız; customer.name gibi noktalı adlar iç içe JSON üretir.
  • Boş kalan değişkenler gövdeye eklenmez. Sabit değerler metin, sayı, evet/hayır veya JSON olabilir.
  • Örnek JSON'dan alan çıkar, API dokümanındaki örnek gövdeden alan adlarını tabloya ekler (doğrulanmaz, değerleri siz seçersiniz).
  • Gelişmiş bölümünde header'lar, query parametreleri ve ham gövde (JSON, form, düz metin) bulunur. Alan tablosu ile ham JSON arasında geçiş yapınca içerik dönüştürülür.

3. Test et ve kaydet

  • İsteği önizle gönderilecek isteği ağ çağrısı yapmadan gösterir (gizli değerler maskeli).
  • Test isteği gönder örnek verilerle isteği bir kez gönderir (dakikada 10 istek). Yanıttaki bir alana tıklayınca yanıt eşleme eklenir: data.tier → http.tier gibi; sonraki adımlarda {{http.tier}} olarak kullanılır.
  • Zaman aşımı (varsayılan 15 sn, en fazla 30), tekrar deneme (varsayılan 2) ve callback ayarları bu bölümde, kapalı bir panelde durur.

Adımın çıkışları Başarılı (2xx) ve Hatadır; callback açıksa Zaman aşımı çıkışı da eklenir. Hata çıkışı bağlı değilse çalıştırma başarısız olarak işaretlenir.

Sonraki adımlarda değişken seçicide Önceki adımlar altında şunlar görünür:

DeğişkenAçıklama
responses.<adım_id>.okİstek başarılı mı
responses.<adım_id>.statusHTTP durum kodu
responses.<adım_id>.error_kindHata nedeni (aşağıda)
responses.<adım_id>.bodyYanıt gövdesinin tamamı

Hata nedenleri (error_kind)

Hata çıkışına bir Switch ekleyip responses.<adım_id>.error_kind değerine göre dallanabilirsiniz:

DeğerAnlamı
http_4xxİstek reddedildi (400, 401, 404…). Tekrar denenmez.
http_5xxSunucu hatası.
http_errorDiğer hata yanıtları (ör. Bitrix24 error zarfı).
timeoutYanıt süresinde gelmedi.
networkBağlantı kurulamadı.
blockedAdres güvenlik kuralına takıldı.
retries_exhausted429, 5xx, zaman aşımı veya ağ hatası tekrar denemelerden sonra da sürdü.

Gerçek çalıştırmaların istek ve yanıtı Çalıştırmalar sayfasında adım ayrıntısında görünür; gizli değerler maskelenir.

Bağlantılar

Bağlantılar sayfasında bir API'yi bir kez tanımlarsınız:

  • Temel adres (https://api.sirketim.com/v1): adımlarda yalnızca yol yazılır.
  • Kimlik doğrulama: aşağıdaki türlerden biri; değer şifreli saklanır, bir daha gösterilmez.
  • Varsayılan header'lar: her isteğe eklenir (Authorization, Cookie, X-API-Key burada yazılamaz, kimlik doğrulama alanını kullanın).
  • Test yolu (ör. /health): Test et bu yola GET atar; sonuç listede görünür.

Aynı sayfada B2B CRM ve Bitrix24 entegrasyonlarının bağlı olup olmadığı görünür.

cURL'den içe aktarmak

API dokümanındaki örnek komutu cURL yapıştır ile içe aktarabilirsiniz. -X, -H, -d / --data-raw / --json, -u, -G ve URL'deki query parametreleri tanınır; bilinmeyen seçenekler uyarı olarak gösterilir.

  • Authorization, X-API-Key veya -u ile gelen gizli bilgiler adıma yazılmaz; yeni bir bağlantı önerilir.
  • URL, kayıtlı bir bağlantının temel adresiyle başlıyorsa o bağlantı ve kalan yol seçilir.
  • Düz (iç içe olmayan) JSON gövdeler alan tablosuna, diğerleri ham JSON'a aktarılır.
  • Komuttaki {{ad}} değişkenleri akış değişkenleriyle eşleştirilir; eşleşmeyenler kırmızı görünür ve elle seçilir.

Güvenlik kuralları

  • Yalnızca herkese açık https adreslerine istek atılır. localhost, özel ağ (10.x, 192.168.x, 172.16–31.x), link-local ve bulut metadata adresleri engellenir.
  • Yönlendirmeler en fazla 3 kez izlenir ve her adımda adres yeniden kontrol edilir.
  • Yanıt gövdesi en fazla 1 MB okunur.
  • Her istekte Idempotency-Key header'ı gönderilir; tekrar denemelerde aynı işlemi iki kez yapmamak için kullanın.

Kimlik doğrulama türleri

TürGönderilen
Bearer tokenAuthorization: Bearer <token>
Basic authAuthorization: Basic base64(kullanıcı:şifre)
API key header<Header adı>: <anahtar> (ör. X-API-Key)
HMAC imzaX-B2B-Timestamp ve X-B2B-Signature header'ları

HMAC imzasını doğrulamak

İmza, "<timestamp>.<ham gövde>" metninin secret ile HMAC-SHA256 özetidir:

X-B2B-Timestamp: 1760000000
X-B2B-Signature: sha256=<hex>

5 dakikadan eski zaman damgalarını reddetmenizi öneririz.

Node.js (Express)

import crypto from "node:crypto";
import express from "express";

const app = express();
app.use(express.text({ type: "*/*" }));

function verify(req, secret) {
  const ts = req.get("X-B2B-Timestamp") || "";
  const sig = (req.get("X-B2B-Signature") || "").replace(/^sha256=/, "");
  if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false;
  const expected = crypto.createHmac("sha256", secret).update(`${ts}.${req.body}`).digest("hex");
  return sig.length === expected.length &&
    crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
}

app.post("/b2b/hook", (req, res) => {
  if (!verify(req, process.env.B2B_SECRET)) return res.status(401).end();
  const data = JSON.parse(req.body || "{}");
  // ... işiniz
  res.json({ ok: true });
});

Python (Flask)

import hashlib, hmac, os, time
from flask import Flask, request, abort

app = Flask(__name__)

def verify(req, secret: str) -> bool:
    ts = req.headers.get("X-B2B-Timestamp", "")
    sig = req.headers.get("X-B2B-Signature", "").removeprefix("sha256=")
    if not ts.isdigit() or abs(time.time() - int(ts)) > 300:
        return False
    body = req.get_data(as_text=True)
    expected = hmac.new(secret.encode(), f"{ts}.{body}".encode(), hashlib.sha256).hexdigest()
    return hmac.compare_digest(sig, expected)

@app.post("/b2b/hook")
def hook():
    if not verify(request, os.environ["B2B_SECRET"]):
        abort(401)
    return {"ok": True}

Callback ile uzun süren işler

Adımda Callback bekle açıksa akış, isteğe yanıt geldikten sonra durur ve sizin geri çağırmanızı bekler. Callback adresi iki yerden iletilir:

  • X-B2B-Callback-Url header'ı
  • Gövdede veya URL'de kullanılabilen {{callback_url}} değişkeni

İşiniz bitince bu adrese JSON POST atın:

curl -X POST "$CALLBACK_URL" \
  -H "Content-Type: application/json" \
  -d '{"status": "done", "report_url": "https://files.example.com/r/42.pdf"}'
  • Callback adresi tek kullanımlıktır. Tekrar çağrılırsa 409, süresi dolmuşsa 410 döner.
  • Adımın bağlantısı HMAC imzalıysa callback de aynı şekilde imzalanmalıdır (X-B2B-Timestamp, X-B2B-Signature); aksi halde 401 döner.
  • Gelen gövdeye yanıt eşleme uygulanır ve akış Başarılı çıkışından devam eder.
  • Süre dolarsa akış Zaman aşımı çıkışından devam eder.

Neden SSH yok? (Runner deseni)

Sunucunuzun SSH anahtarını bizde saklamak yerine sunucunuzda küçük bir HTTP dinleyici (runner) çalıştırmanızı öneriyoruz:

  1. Runner, yukarıdaki imza doğrulamasıyla yalnızca bizden gelen istekleri kabul eder.
  2. İstekteki action alanına göre önceden tanımlı bir komutu çalıştırır; istekten gelen metni doğrudan kabuğa vermez.
  3. Uzun işler için hemen 202 döner, iş bitince X-B2B-Callback-Url adresine sonucu POST eder.
import os, subprocess, threading, httpx
from flask import Flask, request, abort

ACTIONS = {
    "deploy": ["/opt/app/deploy.sh"],
    "report": ["/opt/app/report.sh"],
}

app = Flask(__name__)

@app.post("/run")
def run():
    if not verify(request, os.environ["B2B_SECRET"]):  # yukarıdaki fonksiyon
        abort(401)
    action = (request.get_json(silent=True) or {}).get("action")
    cmd = ACTIONS.get(action)
    if not cmd:
        abort(400)
    callback = request.headers.get("X-B2B-Callback-Url")

    def work():
        proc = subprocess.run(cmd, capture_output=True, text=True, timeout=3600)
        if callback:
            httpx.post(callback, json={"exit_code": proc.returncode, "tail": proc.stdout[-2000:]})

    threading.Thread(target=work, daemon=True).start()
    return {"accepted": True}, 202

Akışı dışarıdan başlatmak için ise Auth & API Keys sayfasındaki POST /api/v1/events/ örneğine bakın.