Skip to content

Webhooks

TurnStay sends real-time notifications to your server when events occur — payment completions, transaction updates, refunds, and more.

TurnStay has two webhook surfaces. Subscribe to the events for the product you integrate:

SurfaceExamplesDocs
Merchant of Recordmerchant_of_record.payment_intent.succeeded, refunds, MOR payoutsPayment Events
Treasurytreasury.payment.completed, treasury.withdraw.completed, deposits, transfersTreasury Events

Receiving MOR events on an endpoint does not mean Treasury events (such as claim confirmations) are delivered. Each event type must be subscribed explicitly.

Configure webhook endpoints in the TurnStay Dashboard under Settings > Webhooks.

All webhooks follow this structure:

{
"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
}
}
}

Your webhook endpoint must:

  • Accept POST requests with a JSON body.
  • Return HTTP 200 to acknowledge receipt.
  • Be publicly accessible (not behind a VPN).
  • Handle duplicate events gracefully (idempotency).
@app.route("/webhooks/turnstay", methods=["POST"])
def turnstay_webhook():
event = request.get_json()
if event["type"] == "merchant_of_record.payment_intent.succeeded":
intent = event["data"]["object"]
mark_booking_as_paid(
reference=intent["merchant_reference"],
amount=intent["billing_amount"],
)
return jsonify({"ok": True}), 200

If your endpoint does not return HTTP 200, TurnStay retries delivery with exponential backoff. Ensure your handler is idempotent — the same event may be delivered more than once.

When an API request fails, TurnStay returns a JSON error response:

{
"detail": "billing_amount is required"
}
HTTP statusMeaning
400Bad request — check the detail field for the cause.
401Unauthorized — invalid or missing API key.
404Resource not found.
405Method not allowed — check the HTTP method.
422Validation error — invalid field values.
500Server error — retry the request or contact support.

If you set callback_url when creating a Payment Intent, TurnStay also POSTs to {your_callback_url}/callback/payment/intent. See Payment Events for the callback payload format.

Webhooks are recommended over callbacks for new integrations.