PayF
← Back to home

developer

Webhook events

PayF posts a webhook each time a payment moves through its lifecycle. Below: every event type, when it fires, and a sample payload you can test against.

Verify signatures

Every webhook carries an X-PayF-Signature header. Always verify it before processing the body — bare HMAC isn't enough, the helper enforces a 5-minute freshness window to defeat replay.

Node / TypeScript

import { verifyWebhook } from "@payf/sdk";

app.post("/webhook", (req, res) => {
  const raw = req.rawBody;              // raw bytes, NOT req.body
  const sig = req.header("x-payf-signature");
  if (!verifyWebhook(raw, sig, process.env.PAYF_WEBHOOK_SECRET!)) {
    return res.status(401).send();
  }
  const event = JSON.parse(raw.toString());
  // ... handle event.event_type ...
});

Python

import payf
from flask import request

@app.post("/webhook")
def webhook():
    body = request.get_data()              # raw bytes
    sig = request.headers["X-PayF-Signature"]
    if not payf.verify_webhook_strict(SECRET, body, sig):
        return "", 401
    event = request.get_json()
    # ... handle event["event_type"] ...
    return "ok"

Go

import payf "github.com/payf-ai/payf-go"

http.HandleFunc("/webhook", func(w http.ResponseWriter, r *http.Request) {
    body, _ := io.ReadAll(r.Body)
    if !payf.VerifyWebhookStrict(
        secret, body,
        r.Header.Get("X-PayF-Signature"),
        time.Now(), payf.DefaultWebhookTolerance,
    ) {
        http.Error(w, "bad signature", 401)
        return
    }
    // ... json.Unmarshal(body, &event) ...
})