Skip to main content

Webhooks

Get notified in real-time when payments are detected, confirmed, or settled.

Setupโ€‹

Set your webhook_url when registering as a merchant, or update it later:

curl -X PATCH https://api.encrypto.fun/checkout/merchants/me \
-H "X-Checkout-Secret-Key: sk_live_xxx" \
-H "Content-Type: application/json" \
-d '{"webhook_url": "https://mystore.com/api/webhooks/encrypto"}'

Verifying Signaturesโ€‹

Every webhook includes an X-Checkout-Signature header. Always verify it to ensure the request came from Encrypto.

Node.jsโ€‹

const crypto = require('crypto');

function verifyWebhook(req) {
const signature = req.headers['x-checkout-signature'];
const body = JSON.stringify(req.body);
const expected = crypto.createHmac('sha256', WEBHOOK_SECRET).update(body).digest('hex');
return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
}

Pythonโ€‹

import hmac, hashlib

def verify_webhook(body: bytes, signature: str, secret: str) -> bool:
expected = hmac.new(secret.encode(), body, hashlib.sha256).hexdigest()
return hmac.compare_digest(signature, expected)

Event Referenceโ€‹

payment.detectedโ€‹

Payment seen on-chain but not yet confirmed. Don't fulfill the order yet.

payment.confirmingโ€‹

Payment has partial confirmations. Almost there.

payment.confirmedโ€‹

Payment fully confirmed. This is when you fulfill the order.

session.expiredโ€‹

The 30-minute window elapsed without payment. Clean up the pending order.

settlement.completedโ€‹

USDC has been settled to your wallet address. This confirms you've been paid out.

Best Practicesโ€‹

  1. Always verify signatures โ€” Never trust unverified webhooks
  2. Return 200 quickly โ€” Process asynchronously if your logic is slow
  3. Handle duplicates โ€” Use session_external_id as an idempotency key
  4. Act on payment.confirmed โ€” Don't fulfill on payment.detected (it could fail)
  5. Log everything โ€” Store the raw webhook payload for debugging