Make real-time authorization decisions for card transactions
Consider carefully before enabling. Due to the constraints of on-chain transactions, card authorizations operate within a tight latency window. Adding real-time authorization introduces additional latency that may result in increased timeout rates and declined transactions. We recommend enabling this feature only if your use case requires real-time decisioning that cannot be achieved through Bridge’s built-in authorization controls.
Real-time authorization allows you to make custom approval or decline decisions during card transactions. When a cardholder attempts to make a purchase, Bridge calls your webhook endpoint synchronously, enabling you to apply your own business logic before the transaction is approved or declined.This gives you fine-grained control over card spending, such as:
Custom spending limits and velocity controls
Merchant category restrictions
Geographic restrictions
Fraud detection and risk scoring
Real-time authorization is optional. If not configured, Bridge will authorize transactions based on available balance and other built-in controls.
Even if your webhook returns approved: true, the transaction may still be declined if the total end-to-end latency exceeds the card network’s timeout. You will be informed of the final authorization result through the regular card transaction webhooks.
The default fallback mode is DECLINE. This means if your webhook is slow or unavailable, transactions will be declined. Consider your use case carefully before changing to APPROVE.
Here’s a complete example webhook handler in Python:
Copy
Ask AI
from flask import Flask, request, jsonifyimport jsonimport base64import timefrom cryptography.hazmat.primitives import hashes, serializationfrom cryptography.hazmat.primitives.asymmetric import paddingapp = Flask(__name__)# Replace with your actual public key from webhook settingsWEBHOOK_PUBLIC_KEY = """-----BEGIN PUBLIC KEY-----your_webhook_public_key_here-----END PUBLIC KEY-----"""def verify_webhook_signature(payload: bytes, signature_header: str, public_key_pem: str) -> bool: try: # Parse signature header signature_parts = signature_header.split(',') timestamp = next((part.split('=', 1)[1] for part in signature_parts if part.startswith('t=')), None) signature = next((part.split('=', 1)[1] for part in signature_parts if part.startswith('v0=')), None) if not timestamp or not signature: return False # Check timestamp (reject events older than 10 minutes) current_time = int(time.time() * 1000) if current_time - int(timestamp) > 600000: return False # Create signed payload signed_payload = f"{timestamp}.{payload.decode()}" # Verify signature public_key = serialization.load_pem_public_key(public_key_pem.encode()) signature_bytes = base64.b64decode(signature) public_key.verify( signature_bytes, signed_payload.encode(), padding.PKCS1v15(), hashes.SHA256() ) return True except Exception: return False@app.route('/webhooks/card-auth', methods=['POST'])def handle_card_authorization(): try: payload = request.get_data() signature_header = request.headers.get('X-Webhook-Signature') if not signature_header: return jsonify({'error': 'Missing signature header'}), 400 # Verify signature if not verify_webhook_signature(payload, signature_header, WEBHOOK_PUBLIC_KEY): return jsonify({'error': 'Invalid signature'}), 400 # Parse webhook data webhook_data = json.loads(payload) auth_data = webhook_data['data'] # Extract authorization details amount = abs(float(auth_data['amount'])) customer_id = auth_data['customer_id'] merchant = auth_data['merchant'] # Implement your business logic here # Examples: # - Check user balance # - Validate merchant category # - Check spending limits # - Run fraud detection # Approve the transaction return jsonify({ 'approved': True }) except Exception as e: print(f"Webhook error: {e}") return jsonify({'error': 'Internal server error'}), 500if __name__ == '__main__': app.run(port=3000)
Test your webhook integration thoroughly in the sandbox environment before going live. Simulate various scenarios including timeouts, errors, and edge cases.