Skip to content

Webhooks

iwocaPay sends a webhook every time an order’s status changes, provided you supplied a webhook_url when you created the order. For how webhooks fit into your integration, see Tracking status changes.

FieldTypeDescription
webhook_urlStringThe URL that iwocaPay sends the webhook payload to for this order.

iwocaPay sends the payload as a POST request with a JSON body to your webhook_url.

{
"data": {
"webhook_id": "f0b4c1e2-9a3d-4f5b-8c6e-1d2a3b4c5d6e",
"event_type": "ORDER_STATUS_CHANGED",
"order_id": "aa8cfc99-3853-4641-8856-3294433b7bb7",
"amount": 278.22,
"reference": "Service Mjolnir",
"status": "CREATED"
}
}
FieldTypeDescription
webhook_idStringA unique ID (UUIDv4) for this webhook delivery.
event_typeStringThe event that triggered the webhook. Currently always "ORDER_STATUS_CHANGED".
order_idStringA unique ID (UUIDv4) for the associated order.
amountNumberThe monetary amount for the order, in GBP.
referenceStringThe order’s reference.
statusEnum, options: "CREATED", "PENDING", "UNSUCCESSFUL", "APPROVED", and "SUCCESSFUL"The status of the order (see Order lifecycle).

Every webhook request includes a signature so you can verify it came from iwocaPay and that the payload has not been tampered with.

The signature is an HMAC-SHA256 hash of the raw request body, keyed with your access token, then Base64-encoded. It is sent in the following header:

X-Iwocapay-Hmac-Sha256: <signature>

To verify a webhook, recompute the signature over the raw request body using your access token, and compare it against the value in the X-Iwocapay-Hmac-Sha256 header. If they don’t match, reject the request.

import base64
import hashlib
import hmac
def is_signature_valid(raw_body: bytes, received_signature: str, token: str) -> bool:
digest = hmac.new(token.encode("utf-8"), raw_body, hashlib.sha256).digest()
expected_signature = base64.b64encode(digest).decode("utf-8")
# Use a constant-time comparison to avoid timing attacks.
return hmac.compare_digest(expected_signature, received_signature)