Webhooks
Handling webhook events across all SDKs.
Overview
Webhooks deliver real-time events to your application.
TypeScript/JavaScript
Express.js
typescript
import express from "express";
import { IslamicOpenFinance } from "@iof/sdk";
const app = express();
const iof = new IslamicOpenFinance({ apiKey: "..." });
app.post(
"/webhooks",
express.raw({ type: "application/json" }),
async (req, res) => {
const signature = req.headers["x-iof-signature"] as string;
try {
const event = iof.webhooks.constructEvent(
req.body,
signature,
process.env.WEBHOOK_SECRET!,
);
switch (event.type) {
case "contract.created":
await handleContractCreated(event.data.object);
break;
case "kyc.verified":
await handleKycVerified(event.data.object);
break;
}
res.status(200).send("OK");
} catch (err) {
console.error("Webhook error:", err);
res.status(400).send("Invalid signature");
}
},
);Next.js
typescript
// app/api/webhooks/route.ts
import { NextRequest, NextResponse } from "next/server";
import { IslamicOpenFinance } from "@iof/sdk";
const iof = new IslamicOpenFinance({ apiKey: "..." });
export async function POST(req: NextRequest) {
const body = await req.text();
const signature = req.headers.get("x-iof-signature")!;
try {
const event = iof.webhooks.constructEvent(
body,
signature,
process.env.WEBHOOK_SECRET!,
);
// Handle event
console.log("Received:", event.type);
return NextResponse.json({ received: true });
} catch (err) {
return NextResponse.json({ error: "Invalid signature" }, { status: 400 });
}
}Python
Flask
python
from flask import Flask, request
from iof import IslamicOpenFinance, WebhookSignatureError
app = Flask(__name__)
iof = IslamicOpenFinance(api_key="...")
@app.route("/webhooks", methods=["POST"])
def webhooks():
payload = request.get_data()
signature = request.headers.get("X-IOF-Signature")
try:
event = iof.webhooks.construct_event(
payload,
signature,
os.environ["WEBHOOK_SECRET"]
)
if event.type == "contract.created":
handle_contract_created(event.data.object)
return "OK", 200
except WebhookSignatureError:
return "Invalid signature", 400FastAPI
python
from fastapi import FastAPI, Request, HTTPException
from iof import IslamicOpenFinance, WebhookSignatureError
app = FastAPI()
iof = IslamicOpenFinance(api_key="...")
@app.post("/webhooks")
async def webhooks(request: Request):
payload = await request.body()
signature = request.headers.get("X-IOF-Signature")
try:
event = iof.webhooks.construct_event(
payload,
signature,
os.environ["WEBHOOK_SECRET"]
)
# Handle event
return {"received": True}
except WebhookSignatureError:
raise HTTPException(status_code=400, detail="Invalid signature")Go
go
import (
"github.com/Islamic-Open-Finance/iof-go/webhook"
)
func webhookHandler(w http.ResponseWriter, r *http.Request) {
payload, _ := io.ReadAll(r.Body)
signature := r.Header.Get("X-IOF-Signature")
event, err := webhook.ConstructEvent(
payload,
signature,
os.Getenv("WEBHOOK_SECRET"),
)
if err != nil {
http.Error(w, "Invalid signature", http.StatusBadRequest)
return
}
switch event.Type {
case "contract.created":
var contract iof.Contract
json.Unmarshal(event.Data.Raw, &contract)
handleContractCreated(&contract)
}
w.WriteHeader(http.StatusOK)
}Java
java
@PostMapping("/webhooks")
public ResponseEntity<String> handleWebhook(
@RequestBody String payload,
@RequestHeader("X-IOF-Signature") String signature
) {
try {
Event event = Webhook.constructEvent(
payload,
signature,
System.getenv("WEBHOOK_SECRET")
);
switch (event.getType()) {
case "contract.created":
handleContractCreated((Contract) event.getData().getObject());
break;
}
return ResponseEntity.ok("OK");
} catch (SignatureVerificationException e) {
return ResponseEntity.badRequest().body("Invalid signature");
}
}Best Practices
- Always verify signatures
- Return 200 quickly - Process async if needed
- Implement idempotency - Handle duplicate events
- Log event IDs - For debugging
- Use HTTPS - Secure endpoints only
Next Steps
- Security Guide - Signature verification
- Webhooks Rail - Endpoint management