Skip to main content

Payout webhook

A55 sends a POST to the webhook_url you set on a payout whenever its status changes. The payload is intentionally minimal — use payout_uuid to fetch the full payout from Get payout.

The webhook_url is provided per payout in the Create payout request body. Private and localhost URLs are rejected.

Payload fields​

FieldTypeDescription
payout_uuidUUIDUnique payout identifier
statusstringNew payout status (see table below)
transaction_referencestringIdempotency key sent on creation
external_idstringProvider's payout id
type_payoutstringPayout rail (pix, bank_transfer, ted, spei, cash_pickup)
payment_codestring or nullCash pickup code (cash payouts only)
authorization_codestring or nullProvider authorization code, when available

Payload example​

{
"payout_uuid": "9b1f0c88-3a3c-4f2f-9d6e-1f0a2d4e88c1",
"status": "realized",
"transaction_reference": "PAY-2048",
"external_id": "MN-20260616-0001",
"type_payout": "pix",
"payment_code": null,
"authorization_code": "AUTH-55812"
}

All possible statuses​

StatusDescription
pendingCreated, awaiting processing
issuedSent to the provider
realizedConfirmed and settled
returnedReturned by the receiving bank
canceledCanceled
errorFailed during processing
expiredExpired

Fetching full payout details​

The webhook payload is minimal by design. After receiving it, call the API with your Bearer token to get the complete payout object:

curl "https://api.a55.tech/api/v1/bank/wallet/payout/{payout_uuid}/{wallet_uuid}/" \
-H "Authorization: Bearer $ACCESS_TOKEN"
Webhook is the trigger, API is the source of truth

Use the webhook to know when a payout changed, then call GET /api/v1/bank/wallet/payout/{payout_uuid}/{wallet_uuid}/ to get full details such as fee, confirmed_date, and destination.

Handler examples​

from flask import Flask, request, jsonify

app = Flask(__name__)
processed = set()

@app.route("/webhooks/a55/payouts", methods=["POST"])
def payout_webhook():
data = request.get_json()
payout_uuid = data.get("payout_uuid")
status = data.get("status")

# Deduplicate
if payout_uuid in processed:
return jsonify(status="duplicate"), 200
processed.add(payout_uuid)

if status == "realized":
mark_payout_settled(payout_uuid)
elif status in ("returned", "error", "expired"):
flag_payout_failure(payout_uuid, status)

return jsonify(status="accepted"), 200

Best practices​

PracticeWhy
Return 200 immediatelyAvoids timeouts and duplicate deliveries
Process in backgroundKeeps response time low
Deduplicate by payout_uuidHandles retried webhooks safely
Fetch full details via APIWebhook payload is minimal by design
Use a public, reachable URLPrivate/localhost URLs are rejected