# Webhook definition

A webhook is a method in the context of Airalo’s API that allows us to seamlessly push real-time data updates to your designated endpoint URL. This ensures timely and efficient data synchronization between our systems and yours.

**Important:** Whenever you perform an opt-in, the webhook_url parameter is checked by the system via a HEAD request. Your endpoint must respond with 200 OK for the opt-in to be considered successful.

We currently support three types of webhooks:
\- _**Async Order**_
\- _**Low Data Notification**_
\- _**Credit Limit Notification**_  

### Custom header for payload signing

To enhance the security and integrity of the transmitted data, our webhook implementation includes a custom header for payload signing. This is an HMAC value generated with the `SHA-512` algorithm. You are strongly encouraged to validate this header in your requests to ensure the authenticity and integrity of the payload.

Header name: `airalo-signature`

**Examples on how to verify the integrity of the received webhook event:**

``` php
function calculateHMAC($data, $key) {
    return hash_hmac('sha512', $data, $key);
}
// Your API secret
define("API_SECRET", "<YOUR_API_SECRET>");
// This is the JSON payload pushed by Airalo's webhook. Depending on the framework you are using, retrieve the payload.
$payload = []; // Assign the actual payload here
$airaloSignature = "<AIRALO_SIGNATURE>"; // Assign the actual header here, located in key `airalo-signature`
// Check if the payload is an object, if so, convert it to a JSON string
if (is_array($payload) || is_object($payload)) {
    $payload = json_encode($payload);
}
// Calculate the expected signature using HMAC with SHA512
$expectedSignature = calculateHMAC($payload, API_SECRET);
if ($expectedSignature === $airaloSignature) {
    // Here you are guaranteed the payload came from Airalo's system, and it is not from any third party or attacker.
    // You can safely proceed with your flow.
    echo 'Yay!';
} else {
    // We wouldn't trust this payload and the system that sent it... Better to reject it or proceed at your own risk.
    echo 'Hmm.... it is suspicious';
}

 ```

``` javascript
const crypto = require('crypto');
const API_SECRET = "<YOUR_API_SECRET>";
// This is the JSON payload pushed by Airalo's webhook. Depending on the framework you are using, retrieve the payload.
let payload = '{}'; // Assign the actual payload here
const airaloSignature = "<AIRALO_SIGNATURE>"; // Assign the actual header here, located in key `airalo-signature`
if (typeof payload === 'object') {
    payload = JSON.stringify(payload);
}
const expectedSignature = crypto.createHmac('sha512', API_SECRET).update(payload).digest('hex');
if (expectedSignature === airaloSignature) {
    // Here you are guaranteed the payload came from Airalo's system, and it is not from any third party or attacker.
    // You can safely proceed with your flow.
    console.log('Yay!');
} else {
    // We wouldn't trust this payload and the system that sent it... Better to reject it or proceed at your own risk.
    console.log('Hmm.... it is suspicious');
}

 ```

``` python
import hashlib
import hmac
import json
API_SECRET = "<YOUR_API_SECRET>"
# This is the JSON payload pushed by Airalo's webhook. Depending on the framework you are using, retrieve the payload.
# Assign the actual payload here
payload = {
    "foo": "bar",
    "baz:": "mqu",
}  # Replace with the actual payload
# Assign the actual header here, located in key `airalo-signature`
airalo_signature = "<AIRALO_SIGNATURE>"
if isinstance(payload, dict):
    payload = json.dumps(payload, separators=(',', ':'))
expected_signature = hmac.new(bytes(API_SECRET, 'utf-8'), msg=bytes(payload, 'utf-8'), digestmod=hashlib.sha512).hexdigest()
if hmac.compare_digest(expected_signature, airalo_signature):
    # Here you are guaranteed the payload came from Airalo's system, and it is not from any third party or attacker.
    # You can safely proceed with your flow.
    print('Yay!')
else:
    # We wouldn't trust this payload and the system that sent it... Better to reject it or proceed at your own risk.
    print('Hmm.... it is suspicious')

 ```

``` java
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
public class AiraloWebhookVerification {
    private static final String API_SECRET = "<YOUR_API_SECRET>";
    public static void main(String[] args) {
        // This is the JSON payload pushed by Airalo's webhook. Depending on the framework you are using, retrieve the payload.
        // Assign the actual payload here
        String payload = "{}";  // Replace with the actual payload
        // Assign the actual header here, located in key `airalo-signature`
        String airaloSignature = "<AIRALO_SIGNATURE>";
        if (payload instanceof String) {
            try {
                MessageDigest digest = MessageDigest.getInstance("SHA-512");
                byte[] hash = digest.digest(payload.getBytes(StandardCharsets.UTF_8));
                payload = bytesToHex(hash);
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            }
        }
        String expectedSignature = generateHmacSHA512(API_SECRET, payload);
        if (expectedSignature.equals(airaloSignature)) {
            // Here you are guaranteed the payload came from Airalo's system, and it is not from any third party or attacker.
            // You can safely proceed with your flow.
            System.out.println("Yay!");
        } else {
            // We wouldn't trust this payload and the system that sent it... Better to reject it or proceed at your own risk.
            System.out.println("Hmm.... it is suspicious");
        }
    }
    private static String generateHmacSHA512(String key, String data) {
        try {
            Mac sha512_HMAC = Mac.getInstance("HmacSHA512");
            SecretKeySpec secret_key = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "HmacSHA512");
            sha512_HMAC.init(secret_key);
            byte[] bytes = sha512_HMAC.doFinal(data.getBytes(StandardCharsets.UTF_8));
            return bytesToHex(bytes);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    private static String bytesToHex(byte[] bytes) {
        StringBuilder result = new StringBuilder();
        for (byte b : bytes) {
            result.append(String.format("x", b));
        }
        return result.toString();
    }
}

 ```
 
 
 
 
 ### Response examples
 Below are response examples for an `HTTP 200` request:   
 
 ```json


// Credit Limit Notification Example
{
    "message": "Surpassed 80% of the credit limit balance",
    "remaining": 225.35
}


// Low Data Notification Example
{
    "level": "3days", // possible values "1days", "3days", "75%", "90%"
    "package_name": "bonbon-7gb-10days",
    "remaining_percentage": 43,
    "iccid": "87123123456889019"
}

 ```
