Webhook (IPN)
Webhook (IPN — Instant Payment Notification) is the mechanism Tingee uses to push notifications to your server as soon as a transaction occurs, so you do not have to keep polling the API.
Flow
🔗Webhook (IPN) processing flow
Transaction
succeeds
succeeds
→
Tingee POSTs
to Webhook URL
to Webhook URL
→
Verify
signature
signature
→
Update
order
order
→
Return
HTTP 200
HTTP 200
Signature verification
Every webhook request from Tingee carries an x-signature header. You must verify it before processing:
Node.js
const crypto = require('crypto');
function verifyWebhookSignature(secretToken, requestTimestamp, body, receivedSignature) {
const expected = crypto
.createHmac('sha512', secretToken)
.update(`${requestTimestamp}:${JSON.stringify(body)}`)
.digest('hex');
return expected === receivedSignature;
}
Python
import hmac, hashlib, json
def verify_signature(secret_token: str, timestamp: str, body: dict, received: str) -> bool:
message = f"{timestamp}:{json.dumps(body, separators=(',', ':'))}"
expected = hmac.new(secret_token.encode(), message.encode(), hashlib.sha512).hexdigest()
return hmac.compare_digest(expected, received)
Ignore requests with an invalid signature
If x-signature does not match, ignore the request entirely. It may be a spoofing attack.
Retry policy
If your endpoint returns an error (anything other than HTTP 200) or times out, Tingee automatically resends:
| Retry | After |
|---|---|
| Retry 1 | 30 seconds |
| Retry 2 | 2 minutes |
| Retry 3 | 10 minutes |
| Retry 4 | 1 hour |
| Retry 5 | 6 hours |
Idempotency
Always use transactionId or orderId to check whether an order has already been processed, to avoid duplicates when you receive a retry.
Event catalog
| Event type | Description |
|---|---|
PAYMENT_SUCCESS | Successful QR / VA transaction |
DEEPLINK_RETURN | Payment result via Deep Link |
DIRECT_DEBIT_RESULT | Direct Debit result |
See the payload structure in detail at Webhook Payment Callback.