Webhooks
Ledgerline receives inbound webhooks from external payment providers to automate payment confirmation and event tracking. This page describes the webhook event model and supported providers.
Prerequisites
- A configured payment provider with webhook support.
- Network access from the provider to your Ledgerline instance's webhook endpoint.
Supported Providers
| Provider | Identifier | Use Case |
|---|---|---|
| PayPal | PAYPAL | Automated payment confirmation. |
| Cash App Pay | CASHAPP_PAY | Automated payment confirmation. |
| Coinbase Commerce | COINBASE_COMMERCE | Cryptocurrency payment confirmation. |
| NOWPayments | NOWPAYMENTS | Automated BTC payment confirmation via BTC_NOWPAYMENTS checkout flow. |
| Discord | DISCORD | Bot interaction events. |
Webhook Event Model
When Ledgerline receives a webhook, it stores the event as a WebhookEvent record:
{
"id": "evt_abc123",
"tenantId": "default",
"provider": "PAYPAL",
"eventId": "WH-12345-67890",
"receivedAt": "2025-01-15T14:30:00.000Z",
"payload": {
"event_type": "PAYMENT.CAPTURE.COMPLETED",
"resource": {
"id": "capture_xyz",
"amount": { "value": "15.00", "currency_code": "USD" }
}
}
}
| Field | Type | Description |
|---|---|---|
tenantId | string | Tenant the event belongs to. |
provider | enum | One of: PAYPAL, CASHAPP_PAY, COINBASE_COMMERCE, DISCORD. |
eventId | string | The provider's unique event identifier (for deduplication). |
receivedAt | Date | Timestamp when Ledgerline received the webhook. |
payload | any | The raw, unmodified event payload from the provider. |
How Webhooks Are Processed
- Receive — The provider sends an HTTP POST to Ledgerline's webhook endpoint.
- Store — Ledgerline persists the raw event as a
WebhookEventrecord for auditing and replay. - Process — The event handler matches the event type and triggers the appropriate business logic (e.g., confirming a payment, updating an order status).
- Acknowledge — Ledgerline returns a
200response to the provider to prevent retries.
Configuring a Provider Webhook
Each payment provider has its own dashboard for configuring webhook URLs. The general steps are:
- Log in to the provider's developer dashboard.
- Navigate to webhook or notification settings.
- Add your Ledgerline webhook URL (provided by your server administrator).
- Select the event types you want to receive (e.g., payment completed, payment failed).
- Save and verify the webhook with a test event.
Consult the specific provider's documentation for detailed setup instructions.
Webhook Event API
The webhook event resource is available via the standard CRUD pattern:
| Operation | Method | Path |
|---|---|---|
| Create | POST | /api/data/webhook-event |
| Read | GET | /api/data/webhook-event/:id |
| Update | PATCH | /api/data/webhook-event/:id |
| Delete | DELETE | /api/data/webhook-event/:id |
These endpoints are primarily for admin inspection and debugging. In normal operation, webhook events are created automatically when a provider sends a notification.
Deduplication
The eventId field (the provider's unique identifier) is used to prevent processing the same event twice. If a provider retries a webhook delivery, Ledgerline can detect the duplicate by eventId and skip reprocessing.
Security Considerations
- Webhook endpoints should validate the authenticity of incoming requests using provider-specific signatures or verification tokens.
- Raw payloads are stored for auditing; sensitive fields within payloads should be handled according to your data retention policies.
- Restrict network access to webhook endpoints to known provider IP ranges where possible.
EasyPost Shipping Webhooks
Ledgerline also receives inbound webhooks from the EasyPost shipping partner. These arrive at POST /api/easypost/webhook and are verified via HMAC-SHA256 (EASYPOST_WEBHOOK_SECRET env var). The body is signed with the secret and compared against the x-hmac-signature header.
When a tracker.updated event arrives, Ledgerline updates the matching shipment record and emits internal shipment.shipped / shipment.delivered / shipment.exception events depending on the new status.
Internal domain events (shipping)
Ledgerline also emits internal domain events for the shipping lifecycle. These are distinct from inbound webhooks — they are emitted on the internal event bus and consumed by feature modules.
| Event | When |
|---|---|
shipment.shipped | An order is marked as shipped (status → in_transit) |
shipment.delivered | A shipment is marked as delivered (future card) |
shipment.exception | A shipment exception is detected (future card) |
order.shipped | Emitted alongside shipment.shipped for order-side consumers |
Consumer integrations (customer DMs, dashboard widgets, entitlement grants) subscribe to these events in their respective cards.