> For the complete documentation index, see [llms.txt](https://coindisco.gitbook.io/coindisco/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://coindisco.gitbook.io/coindisco/white-label-api/webhooks.md).

# Webhooks

Webhooks send transaction updates to a partner HTTPS endpoint.

## Configure an endpoint

Add the endpoint to the widget in the Coindisco dashboard. A widget supports up to five webhook endpoints. Store the generated signature key securely; it is displayed for server-side verification.

The receiver must:

* accept `POST` with `Content-Type: application/json`;
* read the unmodified raw request body;
* verify the `Authorization` signature;
* process `event_id` idempotently;
* return a successful `2xx` response after accepting the event.

## Payload

```json
{
  "event_id": "44cc910c-b0c1-4115-8b9c-a78eeacfbd3a",
  "timestamp": 1765290248,
  "transaction": {
    "transaction_id": "fb352131-473d-4539-992d-49fadc73feac",
    "kind": "buy",
    "status": "completed",
    "raw_status": "COMPLETED",
    "currency_amount": "50.00000000000000000000",
    "cryptocurrency_amount": "0.00046945",
    "wallet_address": "YOUR_WALLET_ADDRESS",
    "service_transaction_id": "provider-order-id",
    "created_at": "2026-07-14T12:54:22+00:00",
    "updated_at": "2026-07-14T14:24:08+00:00"
  }
}
```

The transaction object also contains nested cryptocurrency, currency, network, payment method, region, and service objects, plus available fee and blockchain transaction fields.

## Signature format

The header is:

```
Authorization: {timestamp}.{hex_signature}
```

The signature is lowercase hexadecimal HMAC-SHA256 over:

```
{timestamp}.{raw_request_body}
```

## Python verification example

```python
import hashlib
import hmac
import time


def verify_coindisco_webhook(raw_body: bytes, authorization: str, secret: str) -> bool:
    timestamp_text, received_signature = authorization.split(".", 1)
    timestamp = int(timestamp_text)

    # Choose and enforce a replay window appropriate for your application.
    if abs(int(time.time()) - timestamp) > 300:
        return False

    signed_payload = timestamp_text.encode() + b"." + raw_body
    expected_signature = hmac.new(
        secret.encode(),
        signed_payload,
        hashlib.sha256,
    ).hexdigest()

    return hmac.compare_digest(received_signature, expected_signature)
```

Parse JSON only after verification.

## Delivery behavior

The current delivery task makes one request with a 10-second timeout and does not automatically retry a failed delivery. Partners must use transaction retrieval for reconciliation and should alert on gaps between expected and received updates.
