Skip to main content
AllScale Open API
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)
Webhook payloads are plaintext JSON (not encrypted).

Credentials

When your integration/store is created, you receive:

Important Notes

  • api_secret is 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
  • Store nonce in 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.
So use 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)

  1. Extract headers
  2. Validate timestamp (±300 seconds)
  3. Validate nonce (store with TTL)
  4. Read raw request body bytes (before parsing JSON)
  5. Compute SHA256 of raw body
  6. Rebuild canonical string
  7. Compute expected signature
  8. Timing-safe compare
  9. Only after verification → process payload

Response Expectations

Your endpoint should respond:
  • 200 OK if processed successfully
  • Non-200 if rejected (signature invalid, timestamp invalid, etc.)
AllScale will log the HTTP status and may retry depending on configured policy.

Best Practices

✅ Always verify X-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