# Webhooks

## What is a Webhook?

Webhooks allow your application to receive real-time notifications about events that occur in your account, such as payment link creation, payment completion, or payment failures.

Technically, a webhook is an **HTTP POST request** that Glomo sends to a URL you control, containing a **JSON payload** that describes what happened.

## What is a Webhook URL?

A webhook URL is a publicly accessible HTTPS endpoint on your server that is set up to receive incoming HTTP POST requests from Glomo.

When you configure a webhook in the Glomo dashboard, you provide this URL. Every time an event occurs in your account, Glomo will send the event data to that URL.

**Requirements for a valid webhook URL:**

- Must be publicly accessible over the internet (not `localhost`)
- Must use **HTTPS** (plain HTTP is not accepted)
- Must respond with a `200 OK` status code upon successful receipt
- Must be able to handle POST requests with a JSON body


## How Does a Webhook URL Work? — Step by Step

## Key Things to Know

- Glomo sends webhook notifications as **HTTP POST requests**
- The data is delivered in **JSON format**
- Every webhook payload always contains two important fields:
  - `entity_type` — identifies *what* the webhook is about (e.g. payment, order, payout)
  - `event_type` — identifies *what happened* to it (e.g. success, failed, expired)


## Example Payload Structure

Every webhook payload follows the same top-level structure:


```json
{
  "entity_type": "payment",
  "event_type": "success",
  "data": {
    "id": "payt_686f7cc3pe69T",
    "status": "success",
    ...
  }
}
```

| Field | Type | Description |
|  --- | --- | --- |
| `entity_type` | string | The type of resource this webhook is about (e.g., `payment`, `orders`, `payout`). |
| `event_type` | string | The specific event that occurred on that resource (e.g., `success`, `failed`, `active`). |
| `data` | object | A full snapshot of the resource at the time the event occurred, including IDs, amounts, status, timestamps, and more. |


## Setting Up Webhooks

You can set up to receive webhook events on your account in 3 simple steps.

## Test Connection

You can verify that your webhook URL is correctly set up and reachable by using the **Test Connection** feature in the Glomo dashboard.

![Webhook Test Connection](/assets/webhook-test-connection.9a00b664e14e5c76b7df55444e48f03640e0fc15b8fab96df1990e9f49b8cc8a.a02a8ec9.png)

### How to Test Your Webhook Connection

1. **Save your webhook details first** — Enter your Webhook URL and Secret, then click **Save**. The Test Connection button is only available after the webhook details have been saved.
2. **Click "Test Connection"** — The button is located in the top-right corner of the Webhook Edit page.
3. Glomo will send a test request to your configured webhook URL.


### Possible Responses

| Result | Message |
|  --- | --- |
| ✅ Success | `Webhook connection successful` |
| ❌ Failure | `Request failed with status 422` |


If the test fails, verify that:

- Your webhook URL is publicly accessible over HTTPS
- Your server is returning a `200 OK` response
- There are no firewall or IP restrictions blocking Glomo's requests


## Webhook Authentication & Security

Every webhook request Glomo sends is signed with your webhook secret key. This allows you to verify that the request genuinely came from Glomo and has not been tampered with in transit.

### How Signing Works

When Glomo sends a webhook, it:

1. Takes the raw JSON body of the request.
2. Applies **RFC 8785 JSON canonicalization** to normalize key ordering across different environments.
3. Computes an **HMAC SHA-256** hash of the canonicalized body using your webhook secret key.
4. Attaches the resulting hex-encoded signature to the `X-Glomopay-Signature` request header.


### Verifying the Signature

On your server, you should:

1. Extract the signature from the `X-Glomopay-Signature` header in the incoming webhook request.
2. Apply RFC 8785 JSON canonicalization to the raw request body.
3. Compute the HMAC SHA-256 hash of the canonicalized body using your stored webhook secret key.
4. Compare your computed hash with the value from the header.
5. If the two values match, the webhook is authentic. If they don't match, discard the request.


> **Important:** Never process a webhook payload without first verifying the signature. Skipping this step exposes your system to spoofed or tampered requests.


details
summary
Code Examples
details
summary
PHP

```php
function isValidSignature($payload, $headerSignature, $secretKey) {
    $computedHash = hash_hmac('sha256', $payload, $secretKey);
    return hash_equals($computedHash, $headerSignature);
}
```

details
summary
Ruby

```ruby
require 'openssl'

def is_valid_signature(payload, header_signature, secret_key)
  computed_hash = OpenSSL::HMAC.hexdigest('sha256', secret_key, payload)
  computed_hash == header_signature
end
```

details
summary
Node.js

```javascript
const crypto = require('crypto');

function isValidSignature(payload, headerSignature, secretKey) {
    const computedHash = crypto.createHmac('sha256', secretKey).update(payload).digest('hex');
    return computedHash === headerSignature;
}
```

details
summary
Python

```python
import hmac
import hashlib

def is_valid_signature(payload, header_signature, secret_key):
    computed_hash = hmac.new(secret_key.encode(), payload.encode(), hashlib.sha256).hexdigest()
    return computed_hash == header_signature
```

## What Happens if Your Server Doesn't Respond?

If Glomo sends a webhook to your URL and does not receive a `200 OK` response — whether because your server is down, too slow, returned an error, or responded with any other status code — the delivery is considered failed.

Glomo will **automatically retry** the webhook delivery up to **9 times**, using the following back-off schedule:

| Attempt | Delay After Previous Attempt |
|  --- | --- |
| 1st retry | 1 minute |
| 2nd retry | 5 minutes |
| 3rd retry | 15 minutes |
| 4th retry | 1 hour |
| 5th retry | 3 hours |
| 6th retry | 6 hours |
| 7th retry | 12 hours |
| 8th retry | 24 hours |
| 9th retry | 48 hours |


If all 9 retries are exhausted without a successful `200 OK`, no further delivery attempts will be made for that event.

### Best Practices to Avoid Missed Webhooks

- **Return `200 OK` immediately** — Acknowledge receipt first, then handle processing asynchronously in a background job or queue.
- **Monitor your endpoint** — Set up alerting for 5xx errors or high response times on your webhook endpoint.
- **Design for idempotency** — Since retries can result in the same event being delivered multiple times, ensure your processing logic handles duplicate deliveries safely.


## Glossary

| Term | Definition |
|  --- | --- |
| **Webhook** | An automated HTTP POST request sent by Glomo to your server when a specific event occurs. |
| **Webhook URL** | A publicly accessible HTTPS endpoint on your server configured to receive webhook POST requests from Glomo. |
| **Payload** | The JSON body of the webhook request, containing details about the event that occurred. |
| **`entity_type`** | A field in every webhook payload that identifies the type of resource the event relates to (e.g., `payment`, `payout`, `orders`). |
| **`event_type`** | A field in every webhook payload that identifies what happened to the resource (e.g., `success`, `failed`, `active`). |
| **HMAC SHA-256** | A cryptographic algorithm used to sign webhook payloads. Glomo signs each request; you verify the signature to confirm authenticity. |
| **`X-Glomopay-Signature`** | The HTTP request header that carries the HMAC SHA-256 signature of the webhook payload. |
| **RFC 8785** | A standard for JSON canonicalization — normalizing key ordering before hashing — to ensure consistent signature computation across languages. |
| **Idempotency** | The property of an operation that produces the same result even if applied multiple times. Your webhook handler should be idempotent to handle potential duplicate deliveries safely. |
| **Retry** | An automatic re-delivery of a webhook that did not receive a `200 OK` response. Glomo retries up to 9 times with increasing back-off intervals. |
| **Back-off** | The strategy of waiting progressively longer between retry attempts, reducing load on a struggling server while ensuring eventual delivery. |
| **Secret Key** | A shared secret you configure when setting up a webhook. Glomo uses it to sign payloads; you use it to verify the signature. |
| **Polling** | The alternative to webhooks — repeatedly querying an API to check for updates. Webhooks eliminate the need for polling by pushing updates proactively. |
| **Smallest currency unit** | The convention used for all monetary amounts in Glomo webhooks. Amounts are expressed without decimal points (e.g., $10.00 is sent as `1000`). |