Activity that occurs in Canopy drives many downstream dependent actions. For example, sending email or text notifications to borrowers, executing logic in response to missed borrower payments, and more. All events that occur within the lifecycle of any borrowers on Canopy send webhook notifications for your dependent systems.
Organization-level Webhook URL
To assign your webhook URL to your Canopy organization, navigate to the “App Keys” page from the top right account dropdown. Under the Webhook URL section, paste your webhook URL into that input and hit the save button. Once configured in the Canopy UI, this URL will receive the following events.
Delivery Guarantees
Webhook messages have an ‘at least once’ guarantee. In order to facilitate this, a message may be delivered more than once. It is up to the receiver to detect duplicate messages. This can currently be done with the hmac_signature.
Ordering
There is no guarantee on delivery order of webhooks. If there is an error in receiving the webhook there will be a retry which might change the ordering of webhooks.
Response Pattern
Events will hit your webhook URL in the following pattern:
sql
{"event": String,// The event name"data": Object,// The webhook payload"hmac_signature": String // The signature of the field "data"}
🧠
Your endpoint must respond with a 200 or 202
Other response codes and Retry
Events associated with error codes 429 and 5XX are retried before sent to dead letter queue (DLQ).
Events associated with error codes 1XX, 3XX, and 4XX (excluding 429) aren't retried before sent to DLQ.
Canopy will retry a single webhook event with exponential backoff, with the first retry 1 minute after the first failure, and will stop with the last retry approximately 24 hours after the first failure.
The endpoint will pause if several error codes are received consecutively or if one 401 code is received
Events stored in the dead letter queue (DLQ) are kept for 5 days, and you have the option to resend all DLQ events back to your webhook endpoint. A single put on the Canopy API route /organization/subscribe/replay_failed_events will replay all failed events to your webhook endpoint again.
Verifying HMAC Signatures
You can verify the key on any HMAC library with encryption SHA256 and on Base64. This algorithm needs to be applied on the payload data field, and needs to be equal to the hmac_signature field.
You can retrieve your HMAC secret key via a GET call to Canopy:
If you are testing using controlled processing, you will need to include an additional query parameter in you request to admin/roll/account called roll_webhooks set to true.
Webhooks
Test Event schema: test_event
json
{"welcome":"Welcome to Canopy!","tutorials":"Check out our knowledge base at https://learn.canopyservicing.com","api_reference":"Check out our API docs at https://docs.canopyservicing.com","other_events":"See a full list of supported events at our [event definition page](https://www.notion.so/canopy1/External-Webhook-Events-d9e8bee140674b46a8eca6f426be3a86)","sample_statement":{<Statement -- See Statement Schema Below>},"hmac_signature":"6atLNzJ0KHumzJHwiqzHWO/4cLsYB/KhFppqhQ6IdV4="}
Configurable Webhooks are not enabled by default. You need to explicitly subscribe to them on behalf of each account, with a request to:
PUT /accounts/{{account_id}}/notification_config
Here is a sample subscription payload:
{"notification_type":"payment_due_date",-- the webhook payload(see below)"time_offset":"-1 days",-- time offset from the notification event
"time":"17:00:00"------at which webhook will be triggered in product timezone
}
For this payload, we subscribe to a notification at 5PM, 1 day before the payment due date for the account.
This webhook needs to be configured to be triggered on the date. Examples:
"time_offset": "0 days" ———> triggered on due date +grace days
"time_offset": "6 days" ———> triggered on due date +grace days +6 days
time_offset is always +ve and can be between 0 and cycle length
Retroactive behaviors of minimum_payment_missed
When a retroactive event (i.e payment reversal) has taken place on an account which has had minimum_payment_missed webhooks configured, any future dated webhooks which would have been scheduled as a result of the reversed payment having never taken place will be re-scheduled for the account.
Webhook configurations:
"time_offset": "3 days" ———> minimum_payment_missed webhooks should be delivered 3 days after a missed payment due date.
"time_offset": "6 days" ———> minimum_payment_missed webhooks should be delivered 6 days after a missed payment due date.
Example Retroactivity:
- Payment A, satisfies minimum payment due balance 2 days before the due date
- Payment Reversal of Payment A, occurs 4 days after the due date.
- No minimum_payment_missed will be delivered for the "time_offset": "3 days" configuration as the account is already 4 days past the due date.
- A webhook will be scheduled for the "time_offset": "6 days" configuration as 6 days has not elapsed since the account has missed its due date.
- In the event that an additional payment has been made prior to the scheduled delivery of this webhook, which satisfies the delinquent due balances of the accounts, the scheduled delivery of this webhook will be cancelled.
Note: Using this method, notifications will need to be configured for each individual account after account creation.
Multiple instances of the webhook can be configured. If a periodic configuration exists for an account, it will be the only configuration that will be used.
Example Input Configuration Body
json
If using a time offset:{"notification_type":"account_delinquency","time_offset":"7 days","time":"00:00:00"}
If using a periodic interval:{"notification_type":"account_delinquency","periodic_interval":"DAILY"}
Payload Body Details:
notification_type:
type: string
description: The type of notification whose delivery cadence is being defined for the account.
example: "account_delinquency"
time_offset:
type: string
description: The interval offset from the originating activity from which the notification will be scheduled at. Supports the ISO 8601 interval format.
For account_delinquency the originating activity is an account’s status becoming delinquent.
The offset can not be negative, and has no upper bound.
Can not be used together with periodic_interval
example: "3 days"
If a statement due date is 01/25 and a time_offset is provided for 3 days , a notification will be scheduled for 01/28.
time:
type: string
description: The time of day the notification will be scheduled for in the 24-hour time format.
example: "7:30:00"
When the notification is offset to be scheduled at 01/20 and specifies a time for "7:30:00", the notification will be sent at 07:30 AM on the day of 01/20 at the product’s time zone.
periodic_interval:
type: string
description: The periodicity that will determine when this webhook will be sent, if account remains delinquent
Can not be used together with time_offset or time
Webhook will only be sent when account becomes delinquent and if it still delinquent when callback should be sent
example: "DAILY"
Currently only supports "DAILY" and "WEEKLY"
Retroactive behaviors of account_delinquency
When a retroactive event (i.e payment reversal) has taken place on an account which has had account_delinquency webhooks configured, any future dated webhooks which would have been scheduled as a result of the reversed payment having never taken place will be re-scheduled for the account.
Webhook configurations:
"time_offset": "3 days" ———> account_delinquency webhooks should be delivered 3 days after an account becomes delinquent.
"time_offset": "6 days" ———> account_delinquency webhooks should be delivered 6 days after an account becomes delinquent.
Example Retroactivity:
- Payment A, satisfies minimum payment due balance 2 days before the due date
- Payment Reversal of Payment A, occurs 4 days after the due date.
- No minimum_payment_missed will be delivered for the "time_offset": "3 days" configuration as the account is already 4 days past the due date.
- A webhook will be scheduled for the "time_offset": "6 days" configuration as 6 days has not elapsed since the account has missed its due date.
- In the event that an additional payment has been made prior to the scheduled delivery of this webhook, which cures the account of its delinquent status, the delivery of this webhook will be cancelled.
If a periodic daily configuration exists for an account, using the example above, account_delinquency will begin delivery 1 day after the processing of the payment reversal.
If a periodic weekly configuration exists for an account, using the example above, account_delinquency will begin delivery 1 week after the date at which the account should have become delinquent.
Archived Webhook Payloads
Minimum Payment Due minimum_payment_due — Deprecated in favor of payment_due_date