Payyd Docs

Callbacks

Callback Webhooks

Payyd sends outbound callback messages for Payin and Payout status updates to the callback URL you provide. This page documents the callback payload, headers, signature contract, and verification guidance based on the real backend implementation.

What This Covers
  • When callbacks are sent and when they are skipped.
  • The exact JSON body shape for Payin and Payout updates.
  • The signing headers used for callback delivery.
  • How to reconstruct and verify the HMAC signature on your side.

2

Callback Types

4

Signing Headers

1

HMAC Contract

When Callbacks Are Sent

ConditionBehavior
callbackUrl providedCallback delivery is attempted.
callbackUrl missingNo callback is sent.
message blankNo callback is sent.
Signing credentials availableThe callback is signed with HMAC-SHA256.

Callback Payload

The callback body is the same top-level shape for both Payin and Payout events.

{
  "payydReference": "some_payyd_reference",
  "reference": "your_reference",
  "status": "LinkSent | FundsReceived | PayoutDraft | ...",
  "type": "Payin | Payout",
  "message": "status message"
}

Example: Payin Callback

{
  "payydReference": "PIB26A08D02K10R20D00991",
  "reference": "merchant-payin-001",
  "status": "FundsReceived",
  "type": "Payin",
  "message": "Payin transaction has been completed."
}

Example: Payout Callback

{
  "payydReference": "POU26A08D02K11R05D11881",
  "reference": "merchant-payout-001",
  "status": "PayoutDraft",
  "type": "Payout",
  "message": "Payout transaction has been created."
}

Possible PayinTransactionStatus Values

These values come from the backend enum descriptions and represent the status values you may receive in Payin callbacks or transaction lookups.

StatusDescriptionFinal State?
CancelledCancelledYes
ErrorErrorYes
LinkSentLink SentNo
LinkViewedLink ViewedNo
LinkDeclinedLink DeclinedYes
AwaitingFundsAwaiting FundsNo
LinkAbandonedLink AbandonedYes
FundsCollectedFunds CollectedNo
FundsReceivedFunds ReceivedYes
KYCPendingKYC PendingNo

Possible PayoutTransactionStatus Values

These values come from the backend enum descriptions and represent the status values you may receive in Payout callbacks or transaction lookups.

StatusDescriptionFinal State?
PayoutHoldPayout HoldNo
PayoutDraftPayout DraftNo
PayoutInitiatedPayout InitiatedNo
PayoutProcessingPayout ProcessingNo
PayoutCompletedPayout CompletedYes
PayoutRejectedPayout RejectedYes
PayoutCancelledPayout CancelledYes
ErrorErrorYes
PayoutReturnedPayout ReturnedYes

Headers Sent With The Callback

HeaderMeaning
payyd-requestidUnique UUID generated for the callback request.
x-nonceUnix timestamp in milliseconds.
x-api-keyThe public API key associated with the callback signature.
x-signLowercase HMAC-SHA256 signature of the callback payload.

Signature Contract

The callback signature payload is built from the request id, nonce, API key, and the minified JSON callback body.

{payyd-requestid}::{x-nonce}::{x-api-key}::{minified_json_body}

Payyd then computes a lowercase HMAC-SHA256 using the app secret key.

Receiver-Side Verification Example

$body = file_get_contents('php://input');
$payydRequestId = $_SERVER['HTTP_PAYYD_REQUESTID'] ?? '';
$xNonce = $_SERVER['HTTP_X_NONCE'] ?? '';
$xApiKey = $_SERVER['HTTP_X_API_KEY'] ?? '';
$xSign = $_SERVER['HTTP_X_SIGN'] ?? '';

$message = $payydRequestId . '::' . $xNonce . '::' . $xApiKey . '::' . $body;
$expected = strtolower(hash_hmac('sha256', $message, $yourSecretKey));

if (!hash_equals($expected, $xSign)) {
    http_response_code(401);
    exit('Invalid signature');
}
Implementation note: verify the signature against the exact raw JSON body bytes you receive. Do not deserialize and reserialize the payload before verification, because differences in JSON escaping or field ordering can invalidate the HMAC input.