Webhook events

Silverfin supports a range of webhook events which allow you to track changes in your environment, and can function as a trigger for your own API flows based on such an event.

Currently the API supports the following webhook events:

account.createdan account has been created
account.updatedan account has been updated
account.destroyedan account has been deleted
transaction_document.processeda document is processed attached to a booking (coming from the accountancy system)
permanent_document.processeda document is processed uploaded in the Silverfin documents section
comment.createda new comment is created (currently limited to remarks only, but will be extended to checks as well)
comment.updateda new comment has been updated
comment.destroyeda comment has been deleted
remark.createda new remark is created (can be on any object within Silverfin: company, reconciliation, report, ...)
remark.updateda remark has been updated
remark.destroyeda remark has been deleted
custom.updatedwhen a custom property on a company is created or updated
period.createdwhen a period is unarchived
period.updatedwhen a period is changed from private to public or from public to private
period.destroyedwhen a period is archived
sync_state.updatedwhen a data synchronisation completes or fails, the payload contains if the sync has changed anything
financial_balances.changedwhen there are changes to financial data that might change the trial balances
export.createdwhen a new export PDF is generated
export.destroyedwhen an export has been deleted

The endpoint will send a POST request with a JSON payload to a specified target URL. It will always include the webhook, event, and company sections. The document section mentioned in the example below is specific to events related to documents.

      "id": 1052767521,
      "url": "http://localhost:3001/webhook",
      "events": ["transaction_document.processed", "permanent_document.processed"]
  "event": "permanent_document.processed",
      "id":  398393022,
      "name": "Demo Company"
      "id": 147764866,
      "file_name": "permanent_test_file.docx",
      "content": "This is the content of the file",
      "download_url": "https://live.getsilverfin.com/url_of_the_actual_file",
      "permanent_document_path": ["Contract", "A private document"],
      "permanent_document_id": 411704894

Webhook signature verification

Every request must include two signature headers: X-SF-SIGNATURE-1 and X-SF-SIGNATURE-2. These signatures are generated using your application's webhook_signing_token_1 and webhook_signing_token_2, respectively.

To confirm the authenticity of a request originating from Silverfin, you should compute its Hash-based Message Authentication Code (HMAC) using the SHA-256 digest algorithm, the request's body as data, and a webhook signing token as the key. For instance, in Ruby, you can achieve this as shown below:

OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), WEBHOOK_SIGNING_TOKEN, REQUEST_BODY)

If at least one of the computed signatures matches its respective header, you can consider the request as authentic. Matching with a single signature allows for a seamless rotation of your application's webhook signing tokens.

Retry strategy

When the endpoint doesn't reply with a 2xx code, the post will be retried with an exponential back-off over a total duration of ~48 hours. If after this time the endpoint still doesn't reply with a 2xx code, the webhook subscription will be marked as expired (disabled). Also note that an expired webhook subscription can't be revived, only deleted. To restore its functionality, the subscription will need to be re-created anew.


Silverfin does not throttle outbound webhook events. To protect your application from occasional spikes in incoming events, you may wish to build your own solution or use a third-party service.


Silverfin requires the webhook receiving server to reply within a reasonable time. If the server takes too long to respond, the webhook event will be failed and be retried according to the Retry strategy described above. To avoid timeouts, you should defer processing of the payload until the server replies