Treasury Events
Treasury operations emit webhook events when the status of deposits, withdrawals, transfers, payments, and wallets changes.
Event types
Section titled “Event types”Event names use withdraw (not withdrawal). Subscribe to the names below — these match what TurnStay emits and what appears in the webhook subscription UI.
| Event | Fires when |
|---|---|
treasury.deposit.created | Deposit created. |
treasury.deposit.pending | Deposit is pending. |
treasury.deposit.completed | Deposit funds have been credited to a wallet. |
treasury.deposit.cancelled | Deposit cancelled. |
treasury.withdraw.created | Withdrawal created. |
treasury.withdraw.pending | Withdrawal is pending. |
treasury.withdraw.completed | Withdrawal has been sent to the bank account. |
treasury.withdraw.failed | Withdrawal processing failed. |
treasury.withdraw.cancelled | Withdrawal cancelled. |
treasury.transfer.completed | Inter-wallet transfer completed. |
treasury.transfer.failed | Transfer processing failed. |
treasury.payment.awaiting_claim | Claimable payment created; funds reserved until the recipient claims. |
treasury.payment.pending | Payment is in flight (for example a bank payout after a claim to bank). |
treasury.payment.completed | Payment settled (including after a claim is accepted and settlement finishes). |
treasury.payment.failed | Payment failed. |
treasury.payment.cancelled | Payment cancelled. |
treasury.wallet.created | Wallet created. |
Claimable payments (important)
Section titled “Claimable payments (important)”There is no treasury.payout.* or treasury.withdrawal.* event for claimable wallet payments.
Typical claim flow:
- Sender creates a claimable payment →
treasury.payment.awaiting_claim - Recipient accepts the claim (wallet or bank) and settlement completes →
treasury.payment.completed
treasury.payment.completed is the confirmation that funds have been claimed and settled. It fires when the payment reaches a terminal settled state — not necessarily at the instant the recipient clicks claim. For some bank / external claims, settlement can lag; you may also see treasury.payment.pending while a bank payout is in flight.
Delivery prerequisites
Section titled “Delivery prerequisites”Events are only delivered if your webhook endpoint is configured correctly:
- Subscribe to the exact
treasury.payment.*names in the Dashboard (Listening to / Manage event subscriptions). If you are not subscribed, TurnStay may still accept the internal emit, but nothing is POSTed to your URL. - Merchant of Record is separate. Receiving
merchant_of_record.payment_intent.succeeded(or other MOR events) on the same URL does not mean treasury claim events are delivered. See Payment Events. - Account ID filter (optional). If the endpoint has an Account ID set, it must match the sender wallet id on the event (or leave Account ID empty). A mismatched Account ID silently drops the delivery.
Webhook payload
Section titled “Webhook payload”Claimable payment (example)
Section titled “Claimable payment (example)”{ "type": "treasury.payment.completed", "data": { "object": { "id": "pay_abc123", "company_id": "cmp_xyz", "wallet_id": "wal_sender789", "status": "COMPLETE", "payment_method": "CLAIMABLE", "from_amount": 100000, "to_amount": 100000, "from_currency_code": "ZAR", "to_currency_code": "ZAR", "destination_wallet_id": "wal_dest456", "claim_id": "clm_abc123", "reference": "TIP-001", "error": null, "processed_at": "2026-06-01T10:30:00Z", "exchange_rate_from_to": null } }}Withdrawal (example)
Section titled “Withdrawal (example)”{ "type": "treasury.withdraw.completed", "data": { "object": { "id": "wd_abc123", "company_id": "cmp_xyz", "wallet_id": "wal_xyz789", "status": "completed", "from_amount": 100000, "to_amount": 100000, "from_currency_code": "ZAR", "to_currency_code": "ZAR", "provider_reference": "WD-001", "error": null, "processed_at": "2026-06-01T10:30:00Z" } }}Handling treasury events
Section titled “Handling treasury events”@app.route("/webhooks/turnstay", methods=["POST"])def turnstay_webhook(): event = request.get_json() event_type = event["type"]
if event_type == "treasury.deposit.completed": deposit = event["data"]["object"] update_deposit_status(deposit["id"], "completed") elif event_type == "treasury.withdraw.completed": withdraw = event["data"]["object"] update_withdrawal_status(withdraw["id"], "completed") elif event_type == "treasury.payment.awaiting_claim": payment = event["data"]["object"] mark_payment_awaiting_claim(payment["id"]) elif event_type == "treasury.payment.pending": payment = event["data"]["object"] mark_payment_pending(payment["id"]) elif event_type == "treasury.payment.completed": payment = event["data"]["object"] mark_payment_completed(payment["id"])
return jsonify({"ok": True}), 200