Webhook Event Reference
Complete reference for all EdenPay webhook events and their payload structures.
Event Structure
All webhook events follow this common structure:
{
"id": "evt_abc123",
"type": "payment.confirmed",
"createdAt": "2025-01-15T10:30:00Z",
"data": {
// Event-specific data
}
}
Field | Type | Description |
---|---|---|
id | string | Unique identifier for this event |
type | string | Event type (see below for all types) |
createdAt | string | ISO 8601 timestamp when event was created |
data | object | Event-specific payload |
Payment Events
payment.created
Triggered when a new payment is initiated.
Use case: Track payment creation, start monitoring, or update UI status.
{
"id": "evt_abc123",
"type": "payment.created",
"createdAt": "2025-01-15T10:30:00Z",
"data": {
"paymentId": "pay_xyz789",
"amount": "100.00",
"currency": "USDC",
"network": "ethereum",
"status": "pending",
"recipientAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
"workspaceId": "ws_abc123",
"metadata": {
"orderId": "order_123",
"customerId": "cust_456"
}
}
}
payment.pending
Triggered when a payment transaction is detected on the blockchain but not yet confirmed.
Use case: Show "Payment detected, awaiting confirmation" status to customers.
{
"id": "evt_def456",
"type": "payment.pending",
"createdAt": "2025-01-15T10:31:00Z",
"data": {
"paymentId": "pay_xyz789",
"amount": "100.00",
"currency": "USDC",
"network": "ethereum",
"status": "pending",
"txHash": "0x1234567890abcdef...",
"confirmationsReceived": 1,
"confirmationsRequired": 12,
"recipientAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
"workspaceId": "ws_abc123",
"metadata": {
"orderId": "order_123",
"customerId": "cust_456"
}
}
}
payment.confirmed ⭐
This is the most important event. Triggered when a payment has received sufficient blockchain confirmations and is considered final.
Use case: Fulfill orders, credit accounts, grant access, or trigger any business logic that requires payment confirmation.
This is the event you should use to fulfill orders and grant access to paid content. The payment is irreversible at this point.
{
"id": "evt_ghi789",
"type": "payment.confirmed",
"createdAt": "2025-01-15T10:35:00Z",
"data": {
"paymentId": "pay_xyz789",
"amount": "100.00",
"currency": "USDC",
"network": "ethereum",
"status": "confirmed",
"txHash": "0x1234567890abcdef...",
"confirmationsReceived": 12,
"recipientAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
"workspaceId": "ws_abc123",
"confirmedAt": "2025-01-15T10:35:00Z",
"metadata": {
"orderId": "order_123",
"customerId": "cust_456"
}
}
}
Confirmation Requirements by Network:
- Ethereum: 12 confirmations (~2.5 minutes)
- Polygon: 100 confirmations (~3.5 minutes)
- Base/Optimism: 12 confirmations (~30 seconds)
- Arbitrum: 12 confirmations (~20 seconds)
- Sui: 1 confirmation (~2 seconds)
- Aptos: 1 confirmation (~4 seconds)
payment.failed
Triggered when a payment fails or expires.
Use case: Cancel orders, notify customers, or clean up pending transactions.
{
"id": "evt_jkl012",
"type": "payment.failed",
"createdAt": "2025-01-15T11:00:00Z",
"data": {
"paymentId": "pay_xyz789",
"amount": "100.00",
"currency": "USDC",
"network": "ethereum",
"status": "failed",
"failureReason": "Payment expired after 30 minutes",
"recipientAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
"workspaceId": "ws_abc123",
"metadata": {
"orderId": "order_123",
"customerId": "cust_456"
}
}
}
Common Failure Reasons:
Payment expired after 30 minutes
- Customer didn't complete payment in timeInsufficient amount received
- Customer sent less than requiredWrong network
- Customer sent to wrong blockchainTransaction reverted
- Blockchain transaction failed
payment.refunded
Triggered when a payment is refunded to the customer.
Use case: Revoke access, update accounting, or notify customer of refund.
{
"id": "evt_mno345",
"type": "payment.refunded",
"createdAt": "2025-01-15T12:00:00Z",
"data": {
"paymentId": "pay_xyz789",
"amount": "100.00",
"currency": "USDC",
"network": "ethereum",
"status": "refunded",
"refundTxHash": "0xabcdef1234567890...",
"refundReason": "Customer requested refund",
"recipientAddress": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
"workspaceId": "ws_abc123",
"refundedAt": "2025-01-15T12:00:00Z",
"metadata": {
"orderId": "order_123",
"customerId": "cust_456"
}
}
}
Checkout Session Events
checkout.session.created
Triggered when a new checkout session is created.
Use case: Track checkout funnel, monitor conversion rates.
{
"id": "evt_pqr678",
"type": "checkout.session.created",
"createdAt": "2025-01-15T10:29:00Z",
"data": {
"sessionId": "cs_abc123",
"status": "pending",
"amount": "100.00",
"currency": "USDC",
"network": "ethereum",
"productId": "prod_xyz789",
"workspaceId": "ws_abc123",
"checkoutUrl": "https://checkout.blockeden.xyz/cs_abc123",
"expiresAt": "2025-01-15T11:00:00Z",
"metadata": {
"orderId": "order_123"
}
}
}
checkout.session.completed
Triggered when a checkout session is successfully completed (payment confirmed).
Use case: Track successful checkouts, conversion analytics.
{
"id": "evt_stu901",
"type": "checkout.session.completed",
"createdAt": "2025-01-15T10:35:00Z",
"data": {
"sessionId": "cs_abc123",
"status": "completed",
"amount": "100.00",
"currency": "USDC",
"network": "ethereum",
"productId": "prod_xyz789",
"paymentId": "pay_xyz789",
"workspaceId": "ws_abc123",
"completedAt": "2025-01-15T10:35:00Z",
"metadata": {
"orderId": "order_123"
}
}
}
checkout.session.expired
Triggered when a checkout session expires without payment.
Use case: Track abandoned checkouts, send recovery emails.
{
"id": "evt_vwx234",
"type": "checkout.session.expired",
"createdAt": "2025-01-15T11:00:00Z",
"data": {
"sessionId": "cs_abc123",
"status": "expired",
"amount": "100.00",
"currency": "USDC",
"network": "ethereum",
"productId": "prod_xyz789",
"workspaceId": "ws_abc123",
"expiredAt": "2025-01-15T11:00:00Z",
"metadata": {
"orderId": "order_123"
}
}
}
Event Lifecycle
A typical payment flow produces events in this order:
Alternative flows:
- Payment expires:
payment.failed
→checkout.session.expired
- Payment refunded:
payment.refunded
(after successful payment)
Event Handling Best Practices
1. Handle Events Idempotently
Always check if you've already processed an event:
async function handleWebhook(event) {
// Check if already processed
const existing = await db.webhookEvents.findOne({
eventId: event.id
});
if (existing) {
console.log('Event already processed:', event.id);
return; // Skip duplicate
}
// Process the event
await processPayment(event.data);
// Mark as processed
await db.webhookEvents.create({
eventId: event.id,
type: event.type,
processedAt: new Date()
});
}
2. Use Metadata for Context
Pass your system's IDs through metadata:
// When creating a payment
const payment = await createPayment({
amount: '100.00',
currency: 'USDC',
metadata: {
orderId: 'order_123',
customerId: 'cust_456',
productSku: 'PROD-001'
}
});
// In your webhook handler
function handlePaymentConfirmed(data) {
const { orderId, customerId, productSku } = data.metadata;
await fulfillOrder(orderId, customerId, productSku);
}