LedgerSync API: Webhooks

LedgerSync API: Webhooks

Overview

Webhooks let the LedgerSync API send a notification to your server when something changes, so you do not have to keep polling. Bank connections are asynchronous: a user may finish linking a bank in seconds or take several minutes. A webhook tells you as soon as the connection is active, needs attention or has new data.

You manage webhooks through the API with the /v3/webhooks/subscriptions endpoints. Your API key needs webhook permission to create or change a subscription.

How to subscribe

Send a POST request to /v3/webhooks/subscriptions with a JSON body that holds:

  • url: the address of your endpoint that will receive the notifications.
  • event_types: a list of the events you want, for example connection.active, connection.failed and account.refresh.completed. Use "*" to receive every event.

The response includes a signing_secret. It is shown only in this response (and again only when you rotate it). Save it right away in a secure place. Listing or reading a subscription later does not show it.

Event types

  • connection.requires_action: the connection is waiting on the user, for example to sign in again or finish a security step. This is the first event when a user starts linking.
  • connection.active: the user finished linking and the connection is working.
  • connection.failed: the connection did not complete or stopped working.
  • connection.disconnected: the connection no longer refreshes, or it was deleted through the API.
  • connection.capability_changed: one capability of an active connection changed between working and not working, while the rest of the connection may still work.
  • account.refresh.completed: a data refresh for an account finished successfully.
  • account.refresh.failed: a data refresh for an account failed.
  • statement.available: a bank statement PDF was stored for the first time and is ready to download.

Each delivery is a JSON body with event_id, type, created_at, api_version, livemode and a data object that holds the details for that event.

Verifying the signature

Always verify a delivery before you act on it. Every delivery is a POST with these headers:

  • X-LS-Webhook-Event-Id: a unique ID for the event. Use it to spot duplicates.
  • X-LS-Webhook-Event-Type: the event type, for example account.refresh.completed.
  • X-LS-Webhook-Timestamp: the time the delivery was signed, in Unix seconds.
  • X-LS-Webhook-Signature: the HMAC-SHA256 signature to check.

To check it, join the timestamp, a period and the raw request body (timestamp + "." + raw_body). Compute the HMAC-SHA256 of that text with your signing secret, write it as hex, and compare it to X-LS-Webhook-Signature with a constant-time comparison. We also recommend rejecting deliveries whose timestamp is more than 5 minutes old.

Important: sign the raw bytes of the body exactly as you received them. If your framework parses and re-encodes the JSON first, the bytes change and the signature will not match.

Retries and duplicates

  • Respond with a 2xx status within 10 seconds. Do only the minimum (verify and queue the work), then do slow work in the background. A slow answer, an error status or a dropped connection counts as a failure.
  • A failed delivery is retried with growing waits: 30 seconds, then 1, 2, 5, 15 and 30 minutes, then 1, 2, 4, 8 and 12 hours. After 12 attempts in total, about 28 hours, LedgerSync stops trying that event.
  • Remove duplicates using event_id. The same event can arrive more than once because of retries. If you have already handled an event_id, acknowledge it and skip it.
  • Events can arrive out of order when retries happen. Base your handling on the data in each event rather than on an earlier event having arrived first.

Testing your webhook

Send a POST request to /v3/webhooks/subscriptions/{id}/test to queue a test delivery (event type webhook.test) to your endpoint. The response returns its event_id, which is the same ID the delivery carries. The test is signed with your real signing secret, and it is sent even if webhook.test is not in your list of event types, so it exercises your full verification and duplicate handling.

Managing subscriptions

  • List subscriptions: GET /v3/webhooks/subscriptions. Each subscription shows when it last delivered successfully and when it last failed.
  • Update a subscription: PATCH /v3/webhooks/subscriptions/{id} to change the URL or event types, or to pause and resume deliveries by setting status to paused or active. A paused subscription receives no deliveries.
  • Rotate the signing secret: POST /v3/webhooks/subscriptions/{id}/rotate-secret returns a new signing secret. For 24 hours after a rotation, each delivery also carries an X-LS-Webhook-Signature-Prev header signed with your previous secret, so you can update your servers without missing deliveries.
  • Delete a subscription: DELETE /v3/webhooks/subscriptions/{id} stops all future deliveries. A deleted subscription cannot be turned back on.

Need help?

Email support@ledgersync.com.

Related articles

  • LedgerSync API: Getting Started (Quickstart Guide)
  • LedgerSync API Overview: What You Can Build
  • LedgerSync API: Authentication & API Keys