XPay authenticates API requests with an API key, an account ID, and an HMAC SHA-256 signature. Generate the signature on the merchant backend and send it with the exact serialized request body.
Never expose the API key or API signature secret in browser code, mobile application code, public repositories, or client-side logs.
The merchant can retrieve the API HMAC secret from Store settings → Keys in the XPay Merchant Portal. Treat this value as the API signature secret and use it only on the merchant backend; it is not a publishable SDK credential.
Required headers
Generate the signature
- Construct the exact JSON request body.
- Serialize the body with
JSON.stringify()or the equivalent compact JSON serializer in the integration language. - Generate an HMAC SHA-256 digest using the merchant API signature secret.
- Encode the digest as lowercase hexadecimal text.
- Send the result in
x-signature. - Send the exact serialized body used to calculate the signature.
Node.js example
const crypto = require("crypto");
function signXPayPayload(payload, apiSignatureSecret) {
const serializedPayload = JSON.stringify(payload);
return crypto
.createHmac("sha256", apiSignatureSecret)
.update(serializedPayload)
.digest("hex");
}
const payload = {
amount: 500,
currency: "PKR",
payment_method_types: "card",
customer: {
name: "Ayesha Khan",
email: "ayesha@example.com",
phone: "{{customer_phone}}"
},
metadata: {
order_reference: "order-1001"
}
};
const serializedPayload = JSON.stringify(payload);
const signature = signXPayPayload(
payload,
process.env.XPAY_API_SIGNATURE_SECRET
);Use the same serialized value when sending the request:
const response = await fetch(
"{{base_url}}/public/v1/payment/intent",
{
method: "POST",
headers: {
"Content-Type": "application/json",
"x-api-key": process.env.XPAY_API_KEY,
"x-account-id": process.env.XPAY_ACCOUNT_ID,
"x-signature": signature
},
body: serializedPayload
}
);Diagnose signature failures
Check whether the integration:
- Changed a field after calculating the signature.
- Signed a different payload from the body sent to XPay.
- Serialized the payload differently during signing and transmission.
- Used the API key instead of the API signature secret as the HMAC key.
- Sent credentials from frontend or mobile application code.
Use {{base_url}} in shared examples and obtain the correct environment URL from the XPay Go-Live Guide.