Webhooks
Use signed webhooks as the source of truth for asynchronous payment events.
Alpha sends merchant-facing events with Alpha-owned identifiers. Your receiver should verify the signature, process idempotently, and return 2xx only after durable handling.
Receiver requirements
- Use a public HTTPS endpoint that your system controls.
- Verify X-Alpha-Signature using the exact raw body and timestamp before processing.
- Reject timestamps outside your accepted replay window, typically five minutes.
- Use event_id as an idempotency key in your system.
- Return 2xx only after the event is durably recorded or applied.
- Do not depend on delivery order; fetch the payment from the API if needed.
Signature headers
X-Alpha-Event: payment.completed
X-Alpha-API-Version: 2026-06-08
X-Alpha-Delivery: del_...
X-Alpha-Timestamp: 2026-06-16T12:00:00Z
X-Alpha-Signature: <hmac_sha256>Signature material is the timestamp, a dot, and the exact raw HTTP body:
HMAC-SHA256(endpoint_secret, timestamp + "." + raw_body)Node.js verification
import crypto from "node:crypto";
function verifyAlphaWebhook({ rawBody, timestamp, signature, secret }) {
const signed = Buffer.concat([
Buffer.from(timestamp + "."),
Buffer.isBuffer(rawBody) ? rawBody : Buffer.from(rawBody),
]);
const expected = crypto
.createHmac("sha256", secret)
.update(signed)
.digest("hex");
return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
}Event envelope
{
"id": "evt_...",
"event_id": "evt_...",
"api_version": "2026-06-08",
"type": "payment.completed",
"livemode": false,
"created_at": "2026-06-16T12:00:00Z",
"data": {
"object": {
"object": "payment",
"id": "pay_...",
"amount": "25.00",
"currency": "USD",
"status": "completed",
"reference": "order-a1001"
}
}
}Optional encrypted delivery
Webhook endpoints can use signed-only delivery or encrypted delivery. Signed-only sends readable JSON with HMAC headers. Encrypted delivery wraps the payload with X25519 + AES-GCM, signs the encrypted body, and stores only your public key at Alpha.
- Choose Signed only when your endpoint is already private and your security policy accepts signed JSON.
- Choose Generate key to have Alpha create an X25519 key pair and show the private key once.
- Choose Use my public key when your team manages its own X25519 key pair.
- Store the one-time private key in your secret manager immediately; Alpha cannot recover it.
- Verify the HMAC signature before decrypting the encrypted wrapper.
X-Alpha-Webhook-Encryption: x25519_aesgcm
{
"encrypted": true,
"algorithm": "x25519_aesgcm",
"ephemeral_public_key": "<base64_x25519_public_key>",
"nonce": "<base64_nonce>",
"ciphertext": "<base64_ciphertext>"
}Decryption flow
// Pseudocode: use an X25519 + AES-GCM capable crypto library.
verifyHmac(endpointSecret, timestamp, rawEncryptedBody);
const wrapper = JSON.parse(rawEncryptedBody);
const sharedSecret = x25519(privateKey, base64decode(wrapper.ephemeral_public_key));
const plaintext = aesGcmDecrypt({
key: hkdf(sharedSecret, "alpha-webhook-encryption"),
nonce: base64decode(wrapper.nonce),
ciphertext: base64decode(wrapper.ciphertext),
});
const event = JSON.parse(plaintext);Retries and replay handling
- Alpha retries failed deliveries with exponential backoff up to eight attempts.
- Your receiver should reject old timestamps and duplicate event_id values.
- Manual retries are available from Dashboard > Webhooks > Details.
- A 2xx response means you have durably accepted the event.
- Fetch payment state from /v1/payments/{id} when your system needs a fresh canonical state.
Events merchants can subscribe to
payment.createdpayment.completedpayment.failedpayment.cancelledpayment.refundedpayment.refund_failedrefund.createdrefund.processingrefund.completedrefund.failedmerchant_topup.completedmerchant_topup.failedmerchant_topup.cancelledpayout.createdpayout.requestedpayout.approvedpayout.processingpayout.completedpayout.failedpayout.cancelledpayout.returneddispute.createddispute.evidence_requireddispute.updateddispute.wondispute.lostchargeback.createdchargeback.evidence_requiredchargeback.wonchargeback.lostsettlement.createdsettlement.reconciledsettlement.exception_createdwebhook.test Important
Event names are Alpha-owned. Build merchant logic around Alpha event names, Alpha ids, and Alpha statuses.Testing webhooks
| Tool | Use |
|---|---|
| Test Shop | Create a staging payment and watch the webhook delivery status without building a full storefront. |
| Test Center | Send sample events to subscribed endpoints and simulate settlement, chargeback, and payout outcomes. |
| Dashboard delivery logs | Inspect attempts, response status, next retry, and manually retry failures. |