Verify Webhook Signatures
Verifying the KartaPay-Signature header is required before acting on
a webhook payload.
1. Build the message string
Concatenate these fields, comma-separated, in this exact order:
id,merchantId,clientId,value,currency,submittedAt,status
| Field | Example value | Description |
|---|---|---|
id | 67928bcc4c9deaf5696a0942 | The payment ID |
merchantId | f66d217e-22be-4e8c-a461-bcf9a355190a | Your KartaPay merchant ID (contact KartaPay support) |
clientId | de627e0d87fd2bdcdd7bf72b2c436379 | The reconciliation ID between your system and KartaPay |
value | 1475 | Value of the payment |
currency | KMF | Currency of the payment |
submittedAt | 2025-01-23T18:34:58.846Z | Date the payment was submitted |
status | completed | The payment status |
Example message string:
67928bcc4c9deaf5696a0942,f66d217e-22be-4e8c-a461-bcf9a355190a,de627e0d87fd2bdcdd7bf72b2c436379,1475,KMF,2025-01-23T18:34:58.846Z,completed
The signature covers only id, merchantId, clientId, value,
currency, submittedAt, and status. Other fields present in the
webhook body — topic, timestamp, type, captured, providerId,
source (see Receive Webhooks) — are not
covered by the signature. Do not base security-sensitive decisions on
those unsigned fields; rely on the signed status field, or make a
separate authenticated API call to confirm state, if you need to trust
information the signature doesn't cover.
2. Compute the HMAC-SHA256
Generate an HMAC-SHA256 of that message string using the webhook secret from your dashboard.
Keep your webhook secret safe in your merchant system — anyone with it can forge valid-looking webhooks.
Python
import hmac
import hashlib
secret_key = b'secret_key' # from your KartaPay dashboard
message = b'67928bcc4c9deaf5696a0942,f66d217e-22be-4e8c-a461-bcf9a355190a,de627e0d87fd2bdcdd7bf72b2c436379,1475,KMF,2025-01-23T18:34:58.846Z,completed'
hmac_result = hmac.new(secret_key, message, hashlib.sha256).hexdigest()
print("HMAC-SHA256:", hmac_result)
Node.js
const crypto = require('crypto');
const secretKey = 'secret_key'; // from your KartaPay dashboard
const message = '67928bcc4c9deaf5696a0942,f66d217e-22be-4e8c-a461-bcf9a355190a,de627e0d87fd2bdcdd7bf72b2c436379,1475,KMF,2025-01-23T18:34:58.846Z,completed';
const hmacResult = crypto
.createHmac('sha256', secretKey)
.update(message)
.digest('hex');
console.log('HMAC-SHA256:', hmacResult);
3. Compare signatures
Compare your computed HMAC to the value in the KartaPay-Signature
header. Use a constant-time comparison (e.g. Python's hmac.compare_digest
or Node's crypto.timingSafeEqual) to avoid timing attacks. Only trust the
payload if they match exactly.
:::tip Next step See Errors & Idempotency to handle request failures and retries cleanly. :::