Payment Events
Webhook events
Section titled “Webhook events”Payment Intent events
Section titled “Payment Intent events”| Event | Fires when |
|---|---|
merchant_of_record.payment_intent.created | Payment intent created. |
merchant_of_record.payment_intent.succeeded | Payment successful. |
merchant_of_record.payment_intent.payment_failed | Payment attempt failed. |
merchant_of_record.payment_intent.processing | Payment is being processed. |
Transaction events
Section titled “Transaction events”| Event | Fires when |
|---|---|
merchant_of_record.transaction.created | Transaction created. |
merchant_of_record.transaction.completed | Transaction completed. |
merchant_of_record.transaction.failed | Transaction failed. |
merchant_of_record.transaction.requires_action | Transaction requires additional action (e.g. 3DS). |
Refund events
Section titled “Refund events”| Event | Fires when |
|---|---|
merchant_of_record.refund.created | Refund initiated. |
Chargeback events
Section titled “Chargeback events”| Event | Fires when |
|---|---|
merchant_of_record.chargeback.created | Chargeback opened. |
merchant_of_record.chargeback.completed | Chargeback resolved. |
merchant_of_record.chargeback.reversed | Chargeback reversed in your favour. |
merchant_of_record.chargeback.failed | Chargeback dispute lost. |
Payout events
Section titled “Payout events”| Event | Fires when |
|---|---|
merchant_of_record.payout.created | Payout initiated. |
merchant_of_record.payout.confirmed | Payout confirmed by provider. |
merchant_of_record.payout.applied | Payout applied to your account. |
merchant_of_record.payout.completed | Payout funds delivered. |
merchant_of_record.payout.failed | Payout failed. |
Webhook payload
Section titled “Webhook payload”{ "type": "merchant_of_record.payment_intent.succeeded", "data": { "object": { "id": "45678", "object": "payment_intent", "status": "PROCESSED", "billing_amount": 100000, "billing_currency": "ZAR", "processing_amount": 5200, "processing_currency": "EUR", "merchant_reference": "BOOKING-2026-001", "company_id": 10, "account_id": 123 } }}Callback payload (legacy)
Section titled “Callback payload (legacy)”If you provided callback_url when creating the intent, TurnStay POSTs to {your_callback_url}/callback/payment/intent:
{ "type": "payment_intent.processed", "status": "processed", "payment_intent": { "id": 45678, "status": { "name": "PROCESSED" }, "billing_amount": 100000, "billing_currency": { "code": "ZAR" }, "processing_amount": 5200, "processing_currency": { "code": "EUR" }, "merchant_reference": "BOOKING-2026-001", "customer": "Jean Dupont", "customer_email": "jean.dupont@example.com" }}Callback handler examples
Section titled “Callback handler examples”Python
Section titled “Python”@app.route("/api/turnstay/callback/payment/intent", methods=["POST"])def turnstay_callback(): data = request.get_json() if data["status"] == "processed": intent = data["payment_intent"] mark_booking_as_paid(intent["merchant_reference"], intent["billing_amount"]) return jsonify({"ok": True}), 200Node.js
Section titled “Node.js”app.post("/api/turnstay/callback/payment/intent", (req, res) => { const { status, payment_intent } = req.body; if (status === "processed") { markBookingAsPaid(payment_intent.merchant_reference, payment_intent.billing_amount); } res.status(200).json({ ok: true });});Polling fallback
Section titled “Polling fallback”GET /api/v1/payments/intent?payment_intent_lookup_id=pi_abc123def456Useful for reconciliation, but don’t rely on it as your primary notification method.