Skip to main content

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
FieldExample valueDescription
id67928bcc4c9deaf5696a0942The payment ID
merchantIdf66d217e-22be-4e8c-a461-bcf9a355190aYour KartaPay merchant ID (contact KartaPay support)
clientIdde627e0d87fd2bdcdd7bf72b2c436379The reconciliation ID between your system and KartaPay
value1475Value of the payment
currencyKMFCurrency of the payment
submittedAt2025-01-23T18:34:58.846ZDate the payment was submitted
statuscompletedThe payment status

Example message string:

67928bcc4c9deaf5696a0942,f66d217e-22be-4e8c-a461-bcf9a355190a,de627e0d87fd2bdcdd7bf72b2c436379,1475,KMF,2025-01-23T18:34:58.846Z,completed
Only these 7 fields are signed

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.

danger

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. :::