Skip to main content

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

ProviderIdentifierUse Case
PayPalPAYPALAutomated payment confirmation.
Cash App PayCASHAPP_PAYAutomated payment confirmation.
Coinbase CommerceCOINBASE_COMMERCECryptocurrency payment confirmation.
NOWPaymentsNOWPAYMENTSAutomated BTC payment confirmation via BTC_NOWPAYMENTS checkout flow.
DiscordDISCORDBot 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" }
}
}
}
FieldTypeDescription
tenantIdstringTenant the event belongs to.
providerenumOne of: PAYPAL, CASHAPP_PAY, COINBASE_COMMERCE, DISCORD.
eventIdstringThe provider's unique event identifier (for deduplication).
receivedAtDateTimestamp when Ledgerline received the webhook.
payloadanyThe raw, unmodified event payload from the provider.

How Webhooks Are Processed

  1. Receive — The provider sends an HTTP POST to Ledgerline's webhook endpoint.
  2. Store — Ledgerline persists the raw event as a WebhookEvent record for auditing and replay.
  3. Process — The event handler matches the event type and triggers the appropriate business logic (e.g., confirming a payment, updating an order status).
  4. Acknowledge — Ledgerline returns a 200 response 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:

  1. Log in to the provider's developer dashboard.
  2. Navigate to webhook or notification settings.
  3. Add your Ledgerline webhook URL (provided by your server administrator).
  4. Select the event types you want to receive (e.g., payment completed, payment failed).
  5. 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:

OperationMethodPath
CreatePOST/api/data/webhook-event
ReadGET/api/data/webhook-event/:id
UpdatePATCH/api/data/webhook-event/:id
DeleteDELETE/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.

EventWhen
shipment.shippedAn order is marked as shipped (status → in_transit)
shipment.deliveredA shipment is marked as delivered (future card)
shipment.exceptionA shipment exception is detected (future card)
order.shippedEmitted alongside shipment.shipped for order-side consumers

Consumer integrations (customer DMs, dashboard widgets, entitlement grants) subscribe to these events in their respective cards.