Webhooks

Introduction to Webhooks

Webhooks act as alerts for API events, delivered as they happen.
The Kulipa platform forwards these alerts to an endpoint residing in your environment, specifically set up to accept and handle them.

Create a webhook subscription to receive POST requests from Kulipa when events associated with your application occur.
For managing multiple webhook endpoints and directing various event alerts to each, generate several webhook subscriptions and organize each to relay a particular event notification to a designated endpoint.

📘

Info

Although the majority of applications keep a single webhook subscription, it is possible to have up to five active webhook subscriptions in the Sandbox environment, and a maximum of three in the Production environment simultaneously.

Retry mechanism

If your endpoint fails to respond with a 2xx HTTP status code, Kulipa will retry sending the webhook notification for up to 9 times. The retry interval is as follows: 1, 5, 15 minutes then 1, 4, 12 hours and finally 1, 2, 4 days.

Automatic suspension of a webhook subscription

Kulipa will automatically halt subscribed webhook endpoints that become unreachable.
This measure aids in guaranteeing that unreachable endpoints don't lead to hindrances or problems in the notification delivery for other API users.
Webhook subscriptions may be resumed by invoking this endpoint

IP whitelisting

To ensure the security of your integration, only trust Kulipa webhook notifications from the following IP addresses:

SandboxProduction
xxx.xxx.xxx.xxxxxx.xxx.xxx.xxx

Signature Verification

📘

Info

ECDSA (Elliptic Curve Digital Signature Algorithm) is a cryptographic algorithm used to sign and verify digital messages.
It leverages the properties of elliptic curves to provide strong security while using smaller key sizes compared to traditional methods like RSA.
ECDSA is commonly used in blockchain technology and secure communications.

1. Extract headers signature info

Each webhook notification comes digitally signed with an asymmetric key. Within the headers of every webhook, there will be:

  1. x-kulipa-signature: a header containing the digital signature generated by Kulipa
  2. x-kulipa-signature-ts: a header containing the timestamp generated by Kulipa to avoid replay attack
  3. x-kulipa-key-id: a header containing the UUID used for retrieving a public key for signed messages

2. Fetch public key

With the x-kulipa-key-id value, access the following endpoint to obtain the public key and algorithm utilized for signing the message:

Query

# Replace ${apiKey} with your API key
# Replace ${KulipaKeyId} with your public key id extracted from the header 'x-kulipa-key-id'
curl --request GET \
    --url '/v1/webhooks/keys/${KulipaKeyId}' \
    -H 'accept: application/json' \
    -H 'x-api-key: ${apiKey}'

Response

{
  "data": {
    "id": "${KulipaKeyId}",
    "algorithm": "ECDSA_SHA_256",
    "publicKey": {
      "key": "{publicKeyValueFromKulipa}",
      "type": "spki",
      "format": "pem"
    },
    "createdAt": "{creationDateTimeTZ}"
  }
}

3. Verify body integrity

📘

Info

Ensure that the webhook notification is in the correct JSON string format before verifying it.

With the signature extracted from the headers x-kulipa-signature, the timestamp from x-kulipa-signature-ts, use the public key and algorithm to verify the integrity of the webhook's payload.

The signed payload is created by concatenating:

  • The timestamp (as a string)
  • The character .
  • The actual JSON payload which is the request raw body

Verify from all parameters that the signature provided in the header is valid:

const crypto = require('crypto');

const publicKey = data.publicKey.key;
const publicKeyType = data.publicKey.type;
const publicKeyFormat = data.publicKey.format;
const rawBody = request.body;
const signature = request.headers['x-kulipa-signature'];
const timestamp = request.headers['x-kulipa-signature-ts'];
const signedPayload = `${timestamp}.${rawBody}`;

const verify = crypto.createVerify('SHA256');
verify.update(signedPayload);
verify.end();
const success = verify.verify(
  {
    key: publicKey,
    type: publicKeyType,
    format: publicKeyFormat,
  },
  signature,
  'hex',
);
console.log(success);

📘

Info

To achieve an equality match, calculate the disparity between the current timestamp and the one received, and then determine if this difference falls within your acceptable range.

Manage webhooks

Manage a webhook subscription

Processing webhooks

For the asynchronous handling of webhooks, we advise the execution of the subsequent four steps:

  1. receive
  2. authentication
  3. queueing
  4. processing

1. Receive incoming HTTP calls

Fundamentally, a webhook listener is an HTTP endpoint that Kulipa will interact with. Therefore, your endpoint must:

  • Be capable of accepting POST HTTP requests
  • Handle simultaneous requests
  • Be open to public access
  • Incorporate TLS (with a legitimate SSL certificate registered to your domain)
  • Return HTTP 2xx Status Code within 10 seconds

2. Authentication

When setting up webhook authentication within your application, keep the following considerations in mind:

  • The request body is pre-encoded in JSON before being transmitted. Therefore, the JSON body should never be encoded again; otherwise, the signatures won't align, and authentication will fail, even if the request originated from Kulipa.
  • Your webhook endpoint must be able to access the request body to authenticate the request.
  • Your backend must retrieve the public key associated to the signature key id (extracted from header: x-kulipa-key-id) in order to perform the signature verification

3. Queueing

After receiving the webhook and verifying its origin from Kulipa, we suggest not processing the business logic within the listener directly,
but rather transferring the webhook to a queue for subsequent handling by another backend function.
This approach minimizes the responsibility of your webhook listener, thereby facilitating the rapid and effortless scaling of your application in accordance
with the number of concurrent requests.

4.Processing

After the webhook is received, authenticated, and placed in the queue, and once it has been retrieved from the queue,
it is advisable to look for any duplicate events (webhook event id) and then proceed to manage any particular business logic specific
to your application.

Webhook events list

See our dedicate page listing all events.