Version: v6
Last Updated: 2026-09-09
Overview
AllScale delivers event notifications to your server via Webhook callbacks. Each webhook request is authenticated using HMAC-SHA256 request signing, providing:- Sender authentication (shared secret)
- Payload integrity (tamper-proof)
- Replay attack protection (timestamp + nonce)
- Stateless verification (no session required)
Credentials
When your integration/store is created, you receive:Important Notes
api_secretis shown only once- It cannot be retrieved again
- Store it securely
- Treat it like a password or private key
Webhook Request
Method
Content-Type
Required Headers
Signature Header Format
Replay Protection
To prevent replay attacks:Requirements
- Timestamp must be within ±5 minutes
- Each nonce must be used only once
Recommended Implementation
- Store
noncein Redis - TTL: 600 seconds
- Reject duplicate nonces
Canonical String (v1)
Webhook signatures are generated using a canonical string.Canonical Format
Field Description
⚠️ Important
BODY_SHA256 must be calculated from the raw request body bytes,before JSON parsing or re-serialization.
Signature Algorithm
Algorithm
Encoding
Formula
Header Example
Webhook Payload
The request body sent by AllScale is exactly the following JSON structure.JSON Field Definitions
Verifying a callback
Two fields let you confirm a payment from the callback itself rather than assuming that receiving one means “paid”.status — check it before marking an order paid.
A callback is only ever built on confirmed settlement, so in practice status
is 20. Check it anyway: it is the field that makes the assumption explicit, and
an integration that defaults a missing or unexpected status to “paid” will mark
unpaid orders as paid. Treat anything other than 20 as not paid, and treat
null the same way unless you are knowingly processing a historical callback
from before this field shipped.
actual_paid_amount — it is the buyer’s payment, not always your credit.
Read it as “what the buyer sent”, and note that the two are not always equal:
- When the buyer pays your wallet directly, no platform fee is deducted along the way, so this equals the amount credited to you.
- When the payment is routed through an AllScale temporary wallet, this is the buyer’s gross deposit. AllScale deducts the platform fee before settling to you, so the amount credited to your wallet is lower than this value.
actual_paid_amount to check what the buyer paid against what you
charged. Do not use it as the figure to reconcile your wallet balance
against — use your own on-chain record of the settlement transfer for that.
amount_cents and amount_coins remain the amount you requested, unchanged
by what was actually paid; comparing actual_paid_amount against them is how you
detect an underpayment or overpayment.
Actual Webhook Body Example (Matches Real Structure)
Fiat-priced intent (merchant created with currency)
Stable-coin-priced intent (merchant created with stable_coin)
amount_cents is still an integer and equals amount_coins * 100.
currency and currency_symbol are null — the buyer paid the merchant
directly in coin_symbol, no fiat currency is involved.
Verification Flow (Your Server Side)
- Extract headers
- Validate timestamp (±300 seconds)
- Validate nonce (store with TTL)
- Read raw request body bytes (before parsing JSON)
- Compute SHA256 of raw body
- Rebuild canonical string
- Compute expected signature
- Timing-safe compare
- Only after verification → process payload
Response Expectations
Your endpoint should respond:200 OKif processed successfully- Non-200 if rejected (signature invalid, timestamp invalid, etc.)
Best Practices
✅ Always verifyX-Webhook-Signature before processing✅ Validate timestamp within ±5 minutes
✅ Cache nonce for replay protection
✅ Use idempotency via
webhook_id✅ Convert
amount_coins using Decimal (not float)❌ Never log secrets or signatures
Troubleshooting
End of Document