Verify Webhook Requests
How to verify BagelPay signature on webhook objects.
How to verify BagelPay signature?
BagelPay signature is sent in the Bagelpay-Signature
header of the webhook request. The signature is generated using the HMAC-SHA256 algorithm with the Signing Secret
as the key, and the Request Body and Timestamp
as the message.
To verify the signature, you need to generate the signature using the same algorithm and compare it with the signature sent in the header.
If the two signatures match, the request is authentic.

To generate the Bagelpay-Signature
, you can use the following code example:
import hmac
import hashlib
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
import uvicorn
from pyngrok import ngrok
ngrok.set_auth_token("your_ngrok_key")
WEBHOOK_SECRET = "your_webhook_key"
app = FastAPI()
def verify_webhook_signature(signature_data: bytes, signature: str, secret: str) -> bool:
"""Verify webhook signature for security"""
expected_signature = hmac.new(
secret.encode('utf-8'),
signature_data,
hashlib.sha256
).hexdigest()
print("expected_signature: ", expected_signature)
print("signature: ", signature)
return hmac.compare_digest(expected_signature, signature)
@app.post("/api/webhooks")
async def handle_post(request: Request):
"""Handle BagelPay webhook notifications"""
payload = await request.body()
timestamp = request.headers.get('timestamp').encode()
signature = request.headers.get('Bagelpay-Signature')
# Combine payload and timestamp
signature_data = timestamp + ".".encode() + payload
print("payload: ", payload)
print("timestamp: ", timestamp)
print("signature: ", signature)
print("signature_data: ", signature_data)
if not verify_webhook_signature(signature_data, signature, WEBHOOK_SECRET):
return JSONResponse(status_code=401, content={"error": "Invalid signature"})
print(payload)
return JSONResponse(status_code=200, content={"message": "Success"})
if __name__ == "__main__":
listening_port = "8000"
public_url = ngrok.connect(
addr=listening_port,
proto="http",
hostname="stunning-crane-direct.ngrok-free.app"
)
print(f"ngrok Public URL: {public_url}")
uvicorn.run(app, host="0.0.0.0", port=int(listening_port))

Simply compare the generated Signature with the one received on the header to complete the verification process.
Last updated