Documentation Index
Fetch the complete documentation index at: https://docs.dollarpe.xyz/llms.txt
Use this file to discover all available pages before exploring further.
Webhooks push real-time updates to your server when objects in DollarPe change state. Use them instead of polling. They are the recommended way to drive your integration logic.
How it works
When an event fires, DollarPe sends an HTTP POST to your configured endpoint. Your server must respond with a 2xx status code to acknowledge receipt. Non-2xx responses are treated as delivery failures.
Webhook structure
All events share the same envelope:
{
"type": "string", // Entity type: PAYIN, PAYOUT, CUSTOMER, BANK, EDD
"id": "string", // Unique ID of the entity
"event": "string", // The state the entity moved to
"timestamp": "string", // ISO 8601 timestamp
"metadata": {
"failure_reason": "string" // Present on FAILED events
}
}
Use id to deduplicate events. Webhooks may occasionally be delivered more than once, so your handler should be idempotent.
Signature validation
Every request includes two headers:
X-TIMESTAMP: 1752670745
X-SIGNATURE: ohmVyfuNup6eKWOdOZBBZut5CMPdPTfFSB/zDT/eXQo=
X-TIMESTAMP โ Unix timestamp when the webhook was generated
X-SIGNATURE โ HMAC-SHA256 of the request, Base64 encoded
Validate both on every incoming request. Reject anything with a stale timestamp or a signature mismatch.
import base64
import hmac
import hashlib
import json
def generate_hmac_signature(api_key, api_secret, timestamp, body={}):
body = json.dumps(body, sort_keys=True, separators=(",", ":"))
message = f"{api_key}|{timestamp}|{body}".encode()
signature = hmac.new(api_secret.encode(), message, hashlib.sha256).digest()
return base64.b64encode(signature).decode()
def verify_hmac_signature(api_key, timestamp, signature, body, api_secret):
expected = generate_hmac_signature(api_key, api_secret, timestamp, body)
return hmac.compare_digest(expected, signature)
Usage:
is_valid = verify_hmac_signature(
api_key="your_api_key",
api_secret="your_api_secret",
timestamp=received_timestamp,
signature=received_signature,
body=webhook_body_dict,
)
if not is_valid:
return 401 # reject
Always validate the signature before processing any webhook payload. Never trust the payload without verification.
The metadata object carries event-specific context.
Payin events
failure_reason โ present on FAILED. Values: INCORRECT_UTR, PAYMENT_NOT_RECEIVED, and others. See Failure Reason Reference
refund_reason โ present on REFUND_INITIATED and REFUNDED. Values: INCORRECT_AMOUNT, PAYMENT_FROM_NON_WHITELISTED_ACCOUNT, THIRD_PARTY_PAYMENT
Payout events
utr โ present on SUCCESS. The UTR number for the bank transfer, usable as a reconciliation reference
Customer events
failure_reason โ present on FAILED. Values: DOCUMENT_VERIFICATION_FAILED, TAX_VERIFICATION_FAILED, KYC_FAILED
Bank events
failure_reason โ present on FAILED. Values: ACCOUNT_TYPE_NRE, PENNY_DROP_FAILED, NAME_MISMATCH, BANK_RISK_CHECK_FAILED
Metadata fields are only present when relevant. Successful events typically have an empty metadata object.
Event catalog
Customer events
Fired when a customerโs KYC status changes.
| Event | Description |
|---|
VERIFIED | KYC passed. Customer can link banks and transact |
FAILED | KYC failed or account suspended |
{
"type": "CUSTOMER",
"event": "FAILED",
"id": "12348400-e29b-41d4-a716-446655440000",
"timestamp": "2024-03-13T10:00:00Z",
"metadata": {
"failure_reason": "TAX_VERIFICATION_FAILED"
}
}
Bank events
Fired when a bank account or UPI ID verification resolves.
| Event | Description |
|---|
VERIFIED | Bank account or UPI ID ready for orders |
FAILED | Verification failed |
{
"type": "BANK",
"event": "VERIFIED",
"id": "12348400-e29b-41d4-a716-446655440000",
"timestamp": "2024-03-13T10:00:00Z",
"metadata": {}
}
Payin events
Fired when a payin order changes state.
| Event | Description |
|---|
SUCCESS | Payment received, crypto released |
FAILED | Payin failed |
REFUND_INITIATED | Refund process started |
REFUNDED | Fiat returned to source |
ON_HOLD | Payment flagged and held for review |
{
"type": "PAYIN",
"id": "550e8400-e29b-41d4-a716-446655440000",
"event": "SUCCESS",
"timestamp": "2024-03-13T10:00:00Z",
"metadata": {}
}
{
"type": "PAYIN",
"id": "550e8400-e29b-41d4-a716-446655440000",
"event": "FAILED",
"timestamp": "2024-03-13T10:00:00Z",
"metadata": {
"failure_reason": "INCORRECT_UTR"
}
}
{
"type": "PAYIN",
"id": "550e8400-e29b-41d4-a716-446655440000",
"event": "REFUND_INITIATED",
"timestamp": "2024-03-13T10:00:00Z",
"metadata": {
"refund_reason": "INCORRECT_AMOUNT"
}
}
Payout events
Fired when a payout order changes state.
| Event | Description |
|---|
SUCCESS | Funds delivered to beneficiary |
FAILED | Payout failed |
REFUNDED | Payout amount returned |
CANCELLED | Payout cancelled |
{
"type": "PAYOUT",
"id": "550e8400-e29b-41d4-a716-446655440000",
"event": "SUCCESS",
"timestamp": "2024-03-13T10:00:00Z",
"metadata": {
"utr": "RATN12341234XYZ"
}
}
EDD events
Fired when Enhanced Due Diligence verification resolves.
| Event | Description |
|---|
VERIFIED | EDD passed. Customer gets enhanced payin limits |
FAILED | EDD failed. Standard limits remain |
{
"type": "EDD",
"event": "VERIFIED",
"id": "12348400-e29b-41d4-a716-446655440000",
"timestamp": "2024-03-13T10:00:00Z",
"metadata": {}
}