Event Types
List of supported event types and their payloads.
How to parse and Handle the Webhook Event
Parse the event json
import json
# Example JSON string (as received from API/Webhook)
json_str = r'''
{
"object": {
"mode": "test",
"order": {
"amount": 397.16,
"object": "order",
"status": "paid",
"currency": "usd",
"order_id": "ORD_1967143798153777154",
"created_at": "2025-09-14 08:30:02.653",
"product_id": "prod_1967143613700870145",
"tax_amount": 0,
"updated_at": "2025-09-14 08:30:02.653"
},
"object": "checkout",
"product": {
"mode": "test",
"name": "New_Product_6987",
"price": 397.1632,
"object": "product",
"currency": "USD",
"created_at": "2025-09-14 08:29:20",
"is_archive": true,
"product_id": "prod_1967143613700870145",
"updated_at": "2025-09-14 08:29:22",
"description": "New_Description_of_product_1129",
"billing_type": "subscription",
"tax_category": "ebooks",
"tax_inclusive": false
},
"customer": {
"id": "1967143106647265282",
"email": "andrew@gettrust.ai"
},
"metadata": {
"source": "website",
"campaign": "summer_sale",
"order_id": "req_20250914_162923"
},
"payment_id": "ch_1967143798107639810",
"request_id": "c9b1a4c1-f8ac-40dd-8dea-ba20c92744bb",
"success_url": "https://yourapp.com/success"
},
"event_id": "evt_1S7BJuG2wtflaO0u6Vx3DefT",
"created_at": "2025-09-14 08:30:00",
"event_type": "checkout.completed"
}
'''
# Parse JSON string into Python dictionary
data = json.loads(json_str)
# Process top-level event information
event_id = data.get("event_id")
event_type = data.get("event_type")
event_created_at = data.get("created_at")
print(f"Event ID: {event_id}")
print(f"Event Type: {event_type}")
print(f"Event Created At: {event_created_at}")
# Access the main object section
obj = data.get("object", {})
# Handle the order block
order = obj.get("order", {})
print("\n[Order Information]")
print(f"Order ID: {order.get('order_id')}")
print(f"Amount: {order.get('amount')} {order.get('currency').upper()}")
print(f"Status: {order.get('status')}")
print(f"Created At: {order.get('created_at')}")
print(f"Product ID: {order.get('product_id')}")
print(f"Tax Amount: {order.get('tax_amount')}")
# Handle the product block
product = obj.get("product", {})
print("\n[Product Information]")
print(f"Product ID: {product.get('product_id')}")
print(f"Name: {product.get('name')}")
print(f"Price: {product.get('price')} {product.get('currency')}")
print(f"Description: {product.get('description')}")
print(f"Billing Type: {product.get('billing_type')}")
print(f"Tax Category: {product.get('tax_category')}")
print(f"Is Archived: {product.get('is_archive')}")
# Handle the customer block
customer = obj.get("customer", {})
print("\n[Customer Information]")
print(f"Customer ID: {customer.get('id')}")
print(f"Email: {customer.get('email')}")
# Handle the metadata block
metadata = obj.get("metadata", {})
print("\n[Metadata]")
for key, value in metadata.items():
print(f"{key}: {value}")
# Other information
print("\n[Other Information]")
print(f"Mode: {obj.get('mode')}")
print(f"Payment ID: {obj.get('payment_id')}")
print(f"Request ID: {obj.get('request_id')}")
print(f"Success URL: {obj.get('success_url')}")
Deal with metadata
How metadata Works
metadata WorksWhen creating a checkout session you can attach your own custom info (e.g. internal order_id, campaign) in
metadata.When you receive the webhook after payment, that same
metadatacomes back so you can update your system.
1. Create checkout session with metadata
session = checkout.create_session(
...
metadata={
"source": "website",
"campaign": "summer_sale",
"order_id": "req_20250914_162923"
}
)You pass metadata here so your payment provider stores custom info.
2. Read metadata in webhook
def handle_webhook(event):
if event.get("event_type") == "checkout.completed":
metadata = event["object"].get("metadata", {})
order_id = metadata.get("order_id")
# Use metadata to update your order in DB
print(f"Order {order_id} paid, campaign: {metadata.get('campaign')}")
You set metadata when starting checkout → it comes back unchanged in the webhook → you use it to find and update the correct order in your system.
Event List
checkout.completed
The webhook endpoint will received this event, when:
A one-time payment has been successfully processed, and the fund collection has been finalized.
A recurring subscription payment has been successfully processed.
Sample Request Body
{
"object": {
"mode": "test",
"order": {
"amount": 397.16,
"object": "order",
"status": "paid",
"currency": "usd",
"order_id": "ORD_1967143798153777154",
"created_at": "2025-09-14 08:30:02.653",
"product_id": "prod_1967143613700870145",
"tax_amount": 0,
"updated_at": "2025-09-14 08:30:02.653"
},
"object": "checkout",
"product": {
"mode": "test",
"name": "New_Product_6987",
"price": 397.1632,
"object": "product",
"currency": "USD",
"created_at": "2025-09-14 08:29:20",
"is_archive": true,
"product_id": "prod_1967143613700870145",
"updated_at": "2025-09-14 08:29:22",
"description": "New_Description_of_product_1129",
"billing_type": "subscription",
"tax_category": "ebooks",
"tax_inclusive": false
},
"customer": {
"id": "1967143106647265282",
"email": "andrew@gettrust.ai"
},
"metadata": {
"source": "website",
"campaign": "summer_sale",
"order_id": "req_20250914_162923"
},
"payment_id": "ch_1967143798107639810",
"request_id": "c9b1a4c1-f8ac-40dd-8dea-ba20c92744bb",
"success_url": "https://yourapp.com/success"
},
"event_id": "evt_1S7BJuG2wtflaO0u6Vx3DefT",
"created_at": "2025-09-14 08:30:00",
"event_type": "checkout.completed"
}checkout.failed
The webhook endpoint will received this event, when:
Unsuccessful processing of a one-time payment.
The automatic renew failure for a subscription payment.
A one-time or subscription payment was blocked by Radar.
checkout.cancel
The webhook endpoint will received this event, when:
After an order is initiated and proceeds to third-party payment, if the payment page is closed, the third-party payment system will return a message, triggering a cancel event.
A dispute arises over a payment transaction.
subscription.trialing
The webhook endpoint will received this event, when:
When a new trial subscription is created, BagelPay collected the payment method and create a new trial subscription object in your account, this subscription started a trial period.
subscription.paid
The webhook endpoint will received this event, when:
When a trial period was ends, and the customer completes payment for the initial subscription transaction.
Or when a recurring subscription transaction is successfully paid by the customer at each billing cycle.
subscription.canceled
The webhook endpoint will received this event, when:
A merchant manually clicks the cancel subscription button in the control panel
A customer cancels a subscription via viewOrder, or when a customer unlinks their Visa card, signifying the unbinding and cancellation of the subscription.
refund.created
The webhook endpoint will received this event, when:
When the merchant clicks the refund button in the control panel and processes a refund of any amount, whether it is a partial or full refund.
partial_refund
refunded
Last updated