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

ToolUse
Test ShopCreate a staging payment and watch the webhook delivery status without building a full storefront.
Test CenterSend sample events to subscribed endpoints and simulate settlement, chargeback, and payout outcomes.
Dashboard delivery logsInspect attempts, response status, next retry, and manually retry failures.