Skip to main content

Charge Webhook

A55 sends a POST webhook to your configured URL whenever a charge changes status. Verify the signature before processing any payload.

Payload fields

FieldTypeDescription
charge_uuidUUIDUnique charge identifier
statusstringconfirmed, error, refunded, chargeback
transaction_referencestringAcquirer transaction reference
subscription_uuidUUIDSubscription identifier (if recurring)
amountdecimalCharge amount
currencystringISO 4217 currency code
created_atdatetimeWhen the charge was created
updated_atdatetimeWhen the status last changed

Payload examples

{
"charge_uuid": "chg-001", "status": "confirmed",
"transaction_reference": "txn-abc-123",
"amount": "199.90", "currency": "BRL"
}

Handling code

from flask import Flask, request, jsonify
import hmac, hashlib
app = Flask(__name__)
processed = set()
@app.route("/webhook", methods=["POST"])
def charge_webhook():
sig, ts = request.headers["X-Webhook-Signature"], request.headers["X-Webhook-Timestamp"]
expected = hmac.new(SECRET.encode(), f"{ts}.".encode() + request.data, hashlib.sha256).hexdigest()
if not hmac.compare_digest(expected, sig):
return jsonify(error="invalid signature"), 401
data = request.get_json()
if data["charge_uuid"] in processed:
return jsonify(status="duplicate"), 200
processed.add(data["charge_uuid"])
actions = {"confirmed": fulfill_order, "error": notify_customer,
"refunded": credit_customer, "chargeback": flag_for_review}
if data["status"] in actions:
actions[data["status"]](data)
return jsonify(status="accepted"), 200

Best practices

PracticeWhy
Verify HMAC firstPrevents processing forged payloads
Return 200 immediatelyAvoids timeouts and duplicate deliveries
Process in backgroundKeeps response time under 30 s
Deduplicate by charge_uuidHandles retried webhooks safely
Log raw payloadsEnables debugging without re-delivery
Never trust redirect URL aloneRedirect can be spoofed; webhook is authoritative