Webhooks are automated messages sent from Tonder when transaction events occur. Instead of repeatedly polling our API for status changes, webhooks provide real-time notifications the moment something happens—like a payment completing, failing, or requiring additional authentication. Using webhooks makes your integration more efficient and responsive, ensuring your system stays synchronized with transaction updates in real-time.

Key Events

Tonder sends webhook notifications for various transaction events:
Event TypeDescriptionExample Status Flow
Payment Status ChangesReal-time updates as payments progress through different statespendingauthorizedsuccess
Payment FailuresNotifications when payments are declined or failpendingdeclined or failed
3DS AuthenticationUpdates when users complete 3D Secure challengespending_3dssuccess or failed
Cash Payment ConfirmationsNotifications when customers pay OXXO voucherspendingsuccess (when paid at store)
Withdrawal UpdatesStatus changes for payout transactionsprocessingsuccess or failed

Webhook Payload Structure

All webhook notifications follow a consistent payload structure with these key fields:
FieldTypeDescription
event_typestringThe type of event that occurred (e.g., transaction.status_changed)
event_idstringA unique identifier for this specific webhook event
created_atstringAn ISO 8601 timestamp of when the event occurred
dataobjectThe full transaction object related to the event
data.statusstringThe new, current status of the transaction
data.previous_statusstringThe status of the transaction before this change
Here’s what a typical webhook payload looks like when a payment status changes:
{
  "event_type": "transaction.status_changed",
  "event_id": "evt_123456789",
  "created_at": "2024-07-26T10:32:15Z",
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "operation_type": "payment",
    "status": "success",
    "previous_status": "authorized",
    "amount": 150.00,
    "currency": "MXN",
    "merchant_reference": "order-789",
    "payment_method": "CARD",
    "customer": {
      "name": "Ana María Rodríguez",
      "email": "ana.rodriguez@email.com"
    },
    "completed_at": "2024-07-26T10:32:15Z",
    "authorization_code": "AUTH123456"
  }
}

Getting Started with Webhooks

To start receiving webhook notifications, you need to:
  1. Create a publicly accessible HTTPS URL that can receive POST requests.
  2. Secure your endpoint to verify requests come from Tonder.
  3. Register your endpoint using our API.
  4. Process incoming webhook notifications in your application.
Prerequisites for webhook endpoints:
  • Must use HTTPS (not HTTP) for security.
  • Should respond within 30 seconds to avoid timeouts.
  • Must return a 2xx status code to acknowledge receipt.
  • Should implement authentication to verify request source.

Reliability and Delivery

Tonder ensures reliable webhook delivery through built-in resilience mechanisms:
FeatureDetailsBenefit
Automatic RetriesUp to 3 delivery attempts with 60-second intervals between retriesHandles temporary outages and network issues
Response Timeout30-second timeout per delivery attemptPrevents hanging requests and ensures timely retries
Dead Letter QueueFailed events stored for 30 days with manual reprocessingNo events lost, manual recovery for persistent issues
Success CriteriaAny 2xx HTTP status code within timeout windowSimple and flexible acknowledgment requirements
For complete details on delivery mechanisms and retry policies, see Delivery and Retry Logic.

Common Use Cases

Here are practical examples showing how to implement webhook handlers for the most common scenarios you’ll encounter in production applications:
Handle payment status changes to automatically fulfill orders and notify customers when payments complete or fail.
@app.route('/webhook', methods=['POST'])
def handle_payment_webhook():
    payload = request.get_json()
    
    if payload['event_type'] == 'transaction.status_changed':
        transaction = payload['data']
        
        if transaction['status'] == 'success':
            # Payment completed successfully
            fulfill_order(transaction['merchant_reference'])
            send_confirmation_email(transaction['customer']['email'])
            
        elif transaction['status'] == 'failed':
            # Payment failed
            notify_customer_of_failure(transaction['customer']['email'])
    
    return jsonify({'status': 'received'}), 200
Process 3D Secure authentication completions to finalize payments that required additional customer verification.
def handle_3ds_webhook(payload):
    transaction = payload['data']
    
    if payload['event_type'] == 'transaction.3ds_completed':
        if transaction['status'] == 'success':
            # 3DS authentication successful, payment completed
            complete_order(transaction['id'])
        else:
            # 3DS authentication failed
            cancel_order(transaction['merchant_reference'])

Webhook Management

Now that you understand how webhooks work and have seen practical examples, explore these focused guides to implement webhooks in your application: