Transaction Webhooks
Monitor payments, payouts, and transaction events in real-time
Transaction webhooks notify you instantly when payment and payout events occur. Receive alerts when transactions are processed, declined, refunded, or rejected, enabling you to automate order fulfillment, send customer notifications, and keep your systems synchronized with transaction status changes.
New to Webhooks? If you're new to webhooks or need to understand the basics of webhook setup, security, and debugging, start with the Webhooks Overview guide. This article focuses specifically on transaction-related webhook triggers and workflows.
Prerequisites
Before implementing transaction webhooks, familiarize yourself with these topics.
Learn about webhooks
Understand webhook basics, setup, security, and debugging in the general webhooks guide.
Learn about transactions
Understand transaction lifecycle and status changes that trigger webhook events.
Transaction-Specific Use Cases
Transaction webhooks enable real-time payment automation:
- Order fulfillment - Automatically fulfill, hold, or cancel orders based on payment status
- Customer notifications - Send instant confirmations, failure alerts, and refund notices
- Payment reconciliation - Sync transaction data to accounting systems in real-time
- Failed payment recovery - Retry declined payments and trigger dunning workflows
Transaction webhooks are essential for bank payments that settle asynchronously and card payments requiring additional verification where the final status isn't immediately available. Webhooks notify you of status changes without polling.
Transaction Webhook Triggers
Webhook triggers available for monitoring transaction and payment events.
Payment Lifecycle Events
| Trigger | When It Fires | Common Use Cases |
|---|---|---|
payment | Payment transaction created | Log all payment attempts, fraud monitoring |
processed | Transaction completed successfully | Fulfill orders, send receipts, update inventory |
authorized | Payment authorized (not captured) | Reserve inventory, verify orders before capture |
decline | Payment declined by processor/bank | Notify customer, retry payment, update order status |
adjusted | Transaction amount adjusted | Update accounting, notify customer of changes |
Refund and Void Events
| Trigger | When It Fires | Common Use Cases |
|---|---|---|
refund | Refund transaction created | Update inventory, notify customer, reverse charges |
void | Transaction voided before settlement | Cancel order, release inventory, notify customer |
Rejection Events
| Trigger | When It Fires | Common Use Cases |
|---|---|---|
reject | Transaction rejected after settlement | Handle NSF, invalid accounts, retry payment |
Payout Events
| Trigger | When It Fires | Common Use Cases |
|---|---|---|
payout | Payout transaction created | Track outgoing payments, notify recipients |
Funding Events
| Trigger | When It Fires | Common Use Cases |
|---|---|---|
deposit | Deposit transaction created | Monitor account funding, track cash flow |
withdraw | Withdraw transaction created | Track outgoing funds, monitor cash outflows |
Recurring Payment Events
| Trigger | When It Fires | Common Use Cases |
|---|---|---|
automatic_payment | Scheduled payment triggered | Monitor subscription billing, handle failures |
Transaction Webhook Workflows
Common workflows for handling transaction events.
from flask import Flask, request
app = Flask(__name__)
@app.route("/webhooks/transaction-processed", methods=["POST"])
def handle_processed():
event = request.json
trigger = event["trigger"]
triggered_on = event["triggered_on"]
if trigger == "processed":
transaction = pl.Transaction.get(triggered_on["id"])
fulfill_order(transaction.order_number)
update_order_status(transaction.order_number, "paid")
send_receipt(transaction)
sync_to_accounting(transaction)
return "OK", 200from flask import Flask, request
app = Flask(__name__)
@app.route("/webhooks/transaction-declined", methods=["POST"])
def handle_decline():
event = request.json
trigger = event["trigger"]
triggered_on = event["triggered_on"]
if trigger == "decline":
transaction = pl.Transaction.get(triggered_on["id"])
decline_code = transaction.status["code"]
send_decline_notification(transaction, decline_code)
if can_retry(decline_code):
retry_payment(transaction)
update_order_status(transaction.order_number, "payment_failed")
log_decline(transaction, decline_code)
return "OK", 200from flask import Flask, request
app = Flask(__name__)
@app.route("/webhooks/refund-issued", methods=["POST"])
def handle_refund():
event = request.json
trigger = event["trigger"]
triggered_on = event["triggered_on"]
if trigger == "refund":
refund = pl.Transaction.get(triggered_on["id"])
original_transaction = refund.parent_id
restock_items(original_transaction.order_number)
send_refund_confirmation(refund)
update_order_status(original_transaction.order_number, "refunded")
record_refund(refund)
return "OK", 200from flask import Flask, request
app = Flask(__name__)
@app.route("/webhooks/transaction-rejected", methods=["POST"])
def handle_reject():
event = request.json
trigger = event["trigger"]
triggered_on = event["triggered_on"]
if trigger == "reject":
transaction = pl.Transaction.get(triggered_on["id"])
reject_code = transaction.status["code"]
if reject_code == "insufficient_bal":
handle_nsf(transaction)
notify_customer_nsf(transaction)
schedule_retry(transaction, 7)
if reject_code == "invalid_account_number":
flag_payment_method(transaction.payment_method_id)
request_new_payment_method(transaction)
update_order_status(transaction.order_number, "payment_rejected")
return "OK", 200Async Processing: Always return 200 status immediately to acknowledge webhook receipt, then process events asynchronously. This prevents timeouts and ensures reliable webhook delivery. See Debugging Webhooks for optimization techniques.
Setting Up Transaction Webhooks
Create webhooks for transaction events using the Webhooks API:
Security Required: It's recommended to implement signature verification for production transaction webhooks to prevent unauthorized order fulfillment, refunds, or other malicious actions. See Signature Verification for implementation details.
For complete webhook setup and security, see:
- Webhooks Overview - General webhook creation and configuration
- Signature Verification - Secure webhooks with HMAC-SHA256
- OAuth Authentication - OAuth for protected endpoints
Webhook Event Structure
Transaction webhooks POST a JSON payload with the following structure:
{
"event_id": "evt_abc123xyz",
"trigger": "processed",
"triggered_on": {
"id": "txn_123",
"object": "transaction",
"value": "processed"
}
}Event fields:
- event_id - Unique identifier for this webhook event (use for idempotency)
- trigger - Event type that triggered the webhook (
processed,decline,refund, etc.) - triggered_on.id - ID of the transaction that triggered the event
- triggered_on.object - Object type (always
transactionfor transaction webhooks) - triggered_on.value - Current status value of the transaction
Use event_id for idempotency: The event_id is unique per webhook delivery. Use it to
prevent duplicate processing if the same webhook is delivered multiple times. Don't use
transaction ID for idempotency, as one transaction can trigger multiple webhook events.
Monitoring Transaction Webhooks
Monitor webhook delivery and debug issues using webhook logs:
Common Transaction Webhook Issues
| Issue | Symptoms | Solution |
|---|---|---|
| Duplicate fulfillment | Same order processed multiple times | Implement idempotency using event_id |
| Missing events | Some transactions not triggering webhooks | Check trigger configuration, webhook logs |
| Timeout errors | Webhooks failing with timeout | Optimize handler, defer heavy processing |
For comprehensive debugging, see:
- Debugging Webhooks - Complete troubleshooting guide
Testing Transaction Webhooks
Test transaction webhooks before production deployment:
Testing Checklist
Verify these scenarios with test transactions:
- Triggers successfully received
- Duplicate webhooks don't cause duplicate fulfillment (idempotency)
- Handler processes webhooks within 30 seconds
- Signature verification rejects invalid signatures
- Failed external API calls don't block webhook acknowledgment
For complete testing strategies, see:
- Webhooks Overview - Testing tools and best practices
Transaction Webhook Best Practices
Follow these transaction-specific best practices for reliable payment automation.
Idempotency for Transaction Events
# Track processed webhook events to prevent duplicate fulfillment
from flask import Flask, request
app = Flask(__name__)
processed_events = set()
@app.route("/webhooks/transaction-processed", methods=["POST"])
def handle_processed():
event = request.json
event_id = event["event_id"]
triggered_on = event["triggered_on"]
if event_id in processed_events:
print(f"Event {event_id} already processed")
return "OK", 200
processed_events.add(event_id)
transaction = pl.Transaction.get(triggered_on["id"])
fulfill_order(transaction)
return "OK", 200Use event_id for idempotency checks, not transaction ID. A single transaction can trigger
multiple webhook events (e.g., authorized then processed), so transaction IDs aren't unique
across events.
Handle All Transaction States
from flask import Flask, request
app = Flask(__name__)
@app.route("/webhooks/transaction-events", methods=["POST"])
def handle_transaction_event():
event = request.json
trigger = event["trigger"]
triggered_on = event["triggered_on"]
handlers = {
"processed": handle_processed,
"decline": handle_decline,
"refund": handle_refund,
"reject": handle_reject,
}
handler = handlers.get(trigger)
if handler:
handler(triggered_on["id"])
else:
print(f"Unhandled trigger: {trigger}")
return "OK", 200Monitor Transaction Webhook Health
Track key metrics for transaction webhooks:
- Average time to process webhook events
- Rate of duplicate webhook processing attempts
- Failure rate for each transaction trigger type
Schema Reference
Transaction webhook configuration:
Webhook Configuration for Transactions
triggerbank_account_reject, reject, refund, void, chargeback, chargeback_reversal, automatic_payment, payment, processed, authorized, adjusted, decline, processing_status, deposit, payment_activation:status, payment_link:status, reversal, credit, transaction:operation, transaction:operation:clear, payout, withdrawurlretriesFor complete transaction field reference:
- Transaction API Reference - All transaction fields, properties, and methods
Next Steps
Enhance webhook functionality and transaction automation
Webhook Infrastructure
Master Webhooks Overview for webhook concepts and setup, implement Signature Verification to secure webhook endpoints with HMAC-SHA256, and use Debugging Webhooks to monitor and troubleshoot webhook delivery.
Transaction Processing
Handle Voids and Refunds for refund and void webhooks, process Payment Declines to respond to declined transactions, and understand Transaction Status to track the complete payment lifecycle.
Payment Workflows
Build Recurring Payments to handle automatic payment webhooks, implement Two-Step Processing for authorize and capture workflows, and manage Payment Methods for payment method webhooks.
Related articles
- Webhooks Overview - General webhook guide
- Signature Verification - Webhook security
- Debugging Webhooks - Troubleshooting
- Transactions API Reference - Transaction object reference
- Webhooks API Reference - Webhook object reference