Last updated

Callbacks

TRP delivers asynchronous updates to your callback URL via signed POST requests. Each callback is queued and retried with exponential backoff.

Retry schedule

The KYCAID TRP backend retries failed callbacks at:

1m → 5m → 15m → 30m → 1h → 3h → 6h → 12h → 24h

After 9 unsuccessful attempts the callback is marked FAILED and dropped.

Signature verification

Every callback ships an x-data-integrity header computed as:

HMAC-SHA512( BASE64( request_body ), customer_signing_secret )

Pseudocode:

import crypto from 'node:crypto';

function verify(rawBody, signatureHeader, secret) {
    const base64 = Buffer.from(rawBody, 'utf8').toString('base64');
    const expected = crypto
        .createHmac('sha512', secret)
        .update(base64)
        .digest('hex');
    return crypto.timingSafeEqual(
        Buffer.from(expected),
        Buffer.from(signatureHeader),
    );
}

Callback types

TypeWhenBody
INQUIRYSent by originator VASP to beneficiary VASP after transfers/initiate.{ asset, amount, callback, IVMS101 }
INQUIRY_RESOLUTIONSent by beneficiary VASP back to originator.{ approved, callback }
TRANSFER_RESOLUTIONSent to the originator's callback once the beneficiary VASP approves.{ transferId, status, statusComment, callback }
TRANSFER_CONFIRMATIONSent to the beneficiary's stored callback once txId is broadcast.{ txid }

Respond with 2xx to acknowledge. Any non-2xx response is retried per the schedule above.

OpenAPI webhook references

Schemas for each callback body are defined as webhooks in the OpenAPI document — see the API Reference: webhookInquiry, webhookInquiryResolution, webhookTransferResolution, webhookTransferConfirmation.