Webhooks

Webhooks allow you to subscribe to specific types of events. For example, when an order is completed. Details of the event, including data related to the object (or objects) are sent directly to a callback URL when the event occurs. This allows third party applications to receive real time updates without having to poll for changes.

Get webhooks

GET /v1/companies/5678/webhooks Get all webhooks
GET /v1/companies/5678/webhooks/537 Fetch a single webhook

Webhooks are created at a company level and for each client application that uses them. You may provide filter if you do not wish to receive all events for a topic for a whole company or other condition. See Filtering for more information.

Create a webhook

POST /v1/companies/5678/webhooks Create a webhook

topic must be one of the Supported topics.

address is where the event will be sent to. See Testing a webhook and Verifying webhooks.

format must be one of json or xml.

headers can be one of Authorization or X-*, but not X-Kounta.

Applications may have more than one webhook registered. Each having their own callback URL. Multiple webhooks can be created against the same topic. This will cause multiple events to be emitted with the same data. This may be useful to receive the same event to be delivered to multiple addresses.

POST /v1/companies/5678/webhooks Create a webhook with a filter

filter is an optional attribute to filter events you wish to receive. In the case above only completed orders that were created under the sites with one of those IDs will be emitted.

If no filter is specified then all events related to a topic will be emitted.

See Filtering for a full description.

Update a webhook

PUT /v1/companies/5678/webhooks/537 Update a webhook

The topic, address, format filter and headers can be updated on an existing webhook.

Only attributes that are specified will be updated (replaced). All of the same validation as creating a webhook apply. i.e. When changing the filter you must provide the complete new filter, you cannot edit part of the filter.

Note: Updating a webhook does not affect events that have already been emitted but not yet received by the address.

Delete a webhook

DELETE /v1/companies/5678/webhooks/537 Delete a webhook

Note: If there are events in the queue that have yet to be delivered deleting the webhook will not remove them from the queue and they will still try to be delivered.

Testing a webhook

GET /v1/companies/5678/webhooks/537/test Test a webhook

A test message will be sent to the address of the webhook. It is not guaranteed that this message will be attempted to be delivered immediately. It will be queued like any other event. For practical purposes this should be close to immediate.

The test payload will be in the format of the webhook and include the headers but is not expected to have any useful information relating to the topic both in structure and data.

Supported topics

Webhook topics are available for the following entities:

Filtering

Filtering is optional (to receive all events for a topic). Or you may use one or a combination of multiple filters.

Sites

All topics allow filtering by site ID. Only events that apply to at least one of the site IDs will be emitted.

If site_ids is provided, there must be at least one element.

POST /v1/companies/5678/webhooks Create a webhook with a filter

Attributes

Some topics allow additional filters on attributes. Webhooks are only emitted if at least one of the attributes have changed.

If attributes is provided, there must be at least one element.

POST /v1/companies/5678/webhooks Create a webhook with a filter

See the individual entities for more information.

Exponential backoff

In most cases webhooks are delivered almost immediately after the event. However, if any of the following cases occur when sending the event to address:

  • The server cannot make a connection within 3 seconds.
  • The request could not be completed within 10 seconds.
  • The response code from the request was not 200.

Then the webhook event is marked as failed and will try again later.

To prevent many webhook requests from overwhelming a server that might already be under too much load each retry will create an ever increasing time between each retry of a single webhook.

Up to 10 retries will be executed before the webhook event is permanently deleted from the queue. These times are:

  • Immediately when the event occurs.
  • 1 minute delay before first retry.
  • 2 minute delay before second retry.
  • 4 minute delay before third retry.
  • 8 minute delay before forth retry.
  • 15 minute delay before each retry until 10 retries.

Verifying webhooks

Requests made to the address of your webhook should be verified to ensure they have not been tampered with and are coming from Kounta.

In each event will be a X-Kounta-Signature header which contains a HMAC (using sha256). To verify the request you need the signature token which can be found in the configuration page for your app on Kounta.

Using the body of the request and your signature token you will be able to verify the request. An example in PHP would look like:

$headers['X-Kounta-Signature'] == hash_hmac('sha256', $body, $signatureToken)

Dynamic headers

Webhook headers can contain special values that cause their values to be calculated at the time the webhook is created. For example:

POST /v1/companies/5678/webhooks Create a webhook

A value can only contain a single special value listed below. It cannot be contained in another string.

@TimeInMillis

Provides the epoch time in milliseconds:

X-Timestamp: 1504840447879

@TimeInSeconds

Provides the epoch time in whole seconds:

X-Timestamp: 1504840447

@HMAC

Generate a hash-based message authentication code. There are several options that can be provided in the form of a query string. For example:

@HMAC?algo=sha256&data=TimeInSeconds&as=hex

  • algo can be any of the supported hashing algorithms listed here. If not provided the default is sha256.
  • data must be one of the other special values (without the preceeding @) such as TimeInMillis. You may also use Body which will use the JSON/XML body as a string. If not provided the default is Body.
  • as must be one of base64 or hex. If not provided the default value is hex.