Billwerk+Optimize can issue webhooks that can be used to keep your system in sync and to take customized actions. Webhooks requires you to have a publicly accessible web server listening on port 80 (HTTP) or 443 (HTTPS). These are the only ports supported. Webhooks can be configured with multiple URL's to support a redundant setup where the same webhook is sent to multiple URL's. Below some rules and best practices regarding webhooks:
- Requests are HTTP POSTs
- Connection timeout towards your HTTP server is 10 seconds
- Your endpoint must respond within 10 seconds
- A response with HTTP code
2XX
is considered successful. All other responses are considered as failed (including redirection responses). - The content of a webhook notifies of an event in the Billwerk+Optimize system, the affected resources and event type, but does not in itself cary any state. It is recommended to subsequently use the API to get the updated state of a resource.
- Your endpoint must be idempotent, allowing multiple invocations of the same webhook with the same result as one invocation. This is due to the fact that communication errors can result in a scenario where Billwerk+Optimize considers an invocation as failed even though it has been received. Billwerk+Optimize will retry failed invocations. See below.
- It is recommended to handle webhooks asynchronously by putting received webhooks on a queue or in a database and process asynchronously.
If your firewall require changes to accept webhooks, webhooks will come from one of the following IP addresses 52.18.114.235
or 34.247.100.100
.
The webhook content is in JSON and contains the following parameters (example on the right):
{
"id": "8ab4b56439944e62ababca7954355578",
"event_id": "680bd8055b5c444bb467dcb731c65bf9",
"event_type": "invoice_settled",
"timestamp": "2015-06-25T12:10:00.64Z",
"signature": "7a591eddc400af4c8a64ff551ff90b37d79471bd2c9a5a2fcd4ed6944f39cb09",
"customer": "OVAFIJ",
"payment_method": "ca_b6506f005dce813e408919475f39bffd",
"payment_method_reference": "cs_4468ca21dfde3c37a5736684cf608111",
"subscription": "sub001",
"invoice": "inv-1234",
"transaction" : "28b1af53d7ecd1c487292402a908e2b3",
"credit_note" : "a26c1bf5f656f489f295d0c4748dd003",
"credit" : "inv-12-credit-3241",
}
Parameter | Description |
---|---|
id | Unique id for webhook. If multiple URL's are used each request will have different id's but same event_id . |
event_id | Id of event triggering webhook (see events). |
event_type | The event type (see below and events). |
timestamp | Timestamp in ISO-8601 when the webhook was triggered. |
signature | Signature to verify the authenticity of the webhook. See below. |
customer | (Optional) Customer handle. Included if event relates to a customer resource. |
payment_method | (Optional) Payment method id. Included for the customer_payment_method_added event. |
payment_method_reference | (Optional) Payment method reference. For a Checkout session the reference will be the session id if it has not been explicitly defined when creating the session. |
subscription | (Optional) Subscription handle. Included if event relates to a subscription resource. |
invoice | (Optional) Invoice handle. Is inv-<invoice_number> if invoice was created automatically for subscription. Included if event relates to an invoice resource. |
transaction | (Optional) For invoice events a transaction id is included if the event was result of a transaction, e.g. a card settle transaction. The transaction id the same as refund id for refunds. |
credit_note | (Optional) Credit note id. Included if the event relates to an invoice refund, credit or cancellation. |
credit | (Optional) Credit id. Included if the event is an invoice credit. |
Notice that new parameters might be introduced. It is important that webhook reception is implemented to ignore unknown parameters.
Optionally the signature can be used to validate the authenticity of the webhook id and timestamp. It is calculated as follows:
signature = hexencode(hmac_sha_256(webhook_secret, timestamp + id))
That is
timestamp
andid
is concatenated- The result is encoded using the HMAC algorithm using
webhook_secret
as key and SHA256 digest mode. - The result is hex encoded
The same calculation can be done in the receiving end, allowing authentication of the webhook. The webhook secret is defined in the webhook settings.
Example in PHP:
hash_hmac('sha256', $timestamp . $id, $secret , false);
Example in Java using Apache Commons Codec:
String signature = new HmacUtils(HmacAlgorithms.HMAC_SHA_256, secret).hmacHex(timestamp + id);
Notice that the signature only guarantees that the id
and timestamp
has not been tampered. Replay attacks would still be possible to using same id
and timestamp
. Only having id
and timestamp
in the signature is deliberate as a signature covering all parameters is very inflexible when introducing potential new return parameters. To handle potential replay attacks we recommend to store the id when a webhook has been processed. If the same id is received again it can be ignored just responding with a HTTP 200 OK. This is also an effective way to implement idempotency as recommended above.
An alterntive way to protect the webhook endpoint is to use HTTP Basic Auth. It can be configured for the webhooks in the webhook configuration.
Yet another alternative is to get the full entity status using the API upon receival of a webhook. E.g. get the whole charge object and only rely on the status of this object.
Webhook event types
Webhooks are triggered by events. See event for a complete list if event types and their description. In the Administration and/or using the API, it can be configured which events to generate webhooks for. Not all events will by default generate a webhook.
Webhook retries
Billwerk+Optimize will retry failing webhooks using the following retry intervals: 2 min - 5 min - 10 min - 20 min - 30 min - and then every hour for three days. For test accounts, webhooks will only be retried for 24 hours.
Webhook ordering
Webhooks are delivered in FIFO ordering grouped by customer entity and URL. That is, all webhooks for events relating to the same customer are delivered sequentially and in FIFO order for each URL. E.g. for a combined create customer and subscription operation that results in an invoice to be created right away, the customer created event will be delivered before the subscription created event which will be delivered before the subscription renewal event and invoice created events. The ordering is only guaranteed if webhooks does not fail. A failed webhook will be retried but will not block for subsequent webhook in same grouping.
To limit the number of concurrent webhooks being fired against your system, a limit of five groups is put on each account. As a result at most five concurrent requests will be fired against your system.
We recommend to reduce the error scenarios when receiving webhooks, preferably offloading webhook processing by putting on a queue or in database, and then have an asynchronous job to process the webhooks.
Webhook alerting
In the Billwerk+Optimize administration under Webhook configuration, alerting can be enabled that will send emails to a number of recipients if webhooks fail. An alert will be sent at most once for each failing webhook. To limit the amount of alerts, at most one email will be sent every 30 minutes per account.