Skip to main content

Overview

StableStack sends webhook events for transaction status changes across wallet deposits, withdrawals, and payouts. Each event includes a signed payload for verification and the complete transaction details.

Event Types

Wallet Events

wallet.transaction.inbound

Description: Triggered when a deposit/inbound transaction completes successfully. Triggered When:
  • User receives funds via Circle wallet deposit
  • Transaction status changes to COMPLETED
  • Funds are reflected in user’s wallet
Payload Example:
Important Fields:
  • `amount`: Transaction amount (string, decimal)
  • `asset_code`: Asset code (USDC, etc.)
  • `network`: Blockchain network (polygon, ethereum, etc.)
  • `crypto_transaction_id`: On-chain transaction hash
  • `status`: Always COMPLETED for this event
  • `balance`: User’s wallet balance after transaction
  • `sender_user`: Nested object with sender identity details
  • `receiver_user`: Nested object with receiver identity details
  • `receiver_wallet_details`: Wallet address and network info

wallet.transaction.outbound

Description: Triggered when a withdrawal/outbound transaction completes or updates. Triggered When:
  • User initiates a withdrawal via Circle wallet
  • Transaction reaches CONFIRMED or COMPLETE state
  • Transaction fails with FAILED status
Payload Example:
Important Fields:
  • `status`: COMPLETED or FAILED
  • `crypto_transaction_id`: On-chain transaction hash
  • `sender_wallet_details`: Originating wallet info
  • `receiver_wallet_details`: Destination wallet info

Payout Events

payout.initiated

Description: Triggered when a payout request is initiated and confirmed. Triggered When:
  • User initiates a fiat payout (ZAR, NGN, USD, etc.)
  • Transaction enters PROCESSING status
Payload Example:
Important Fields:
  • `recipient_currency`: Target fiat currency (ZAR, NGN, USD, etc.)
  • `bank_name`: Receiving bank for the payout
  • `bank_account`: Bank account number (masked where possible)
  • `reference_id`: transaction reference

payout.processing

Description: Triggered when a payout is actively being processed. Triggered When:
  • Payout passes initial validation
  • Funds are being transferred to the recipient bank
  • Processing has started
Payload Example:
Important Fields:
  • `recipient_currency`: Target fiat currency (ZAR, NGN, USD, etc.)
  • `bank_name`: Receiving bank for the payout
  • `bank_account`: Bank account number
  • `withdrawal_recipient_name`: Recipient name at receiving bank
  • `reference_id`: transaction reference

payout.completed

Description: Triggered when a payout reaches the recipient’s bank account successfully. Triggered When:
  • Funds are confirmed received at destination bank
  • confirms successful completion
  • Transaction status changes to COMPLETED
Payload Example:
Important Fields:
  • `status`: Always COMPLETED for this event
  • `reference_id`: Use for tracking
  • `bank_account`: Receiving bank account
  • `withdrawal_recipient_name`: Recipient name at receiving bank

payout.failed

Description: Triggered when a payout fails at any stage. Triggered When:
  • Bank rejects the transfer
  • Insufficient funds or invalid account details
  • Transaction status changes to FAILED
Payload Example:
Important Fields:
  • `status`: Always FAILED for this event
  • `reference_id`: Use for tracking
  • `bank_account`: Intended receiving bank account

payout.cancelled

Description: Triggered when a payout is cancelled. Triggered When:
  • User cancels the payout before processing
  • Admin cancels the transaction
  • Cancels due to compliance/fraud checks
  • Transaction status changes to CANCELLED
Payload Example:
Important Fields:
  • `status`: Always CANCELLED for this event
  • `reference_id`: Use for tracking

Webhook Payload Structure

All webhook payloads follow this structure:
Fields:
  • `id`: Unique event ID
  • `timestamp`: Unix timestamp in milliseconds
  • `event_type`: Event type string
  • `data`: Event-specific transaction data

Signature Verification

All webhooks are signed with HMAC-SHA256. To verify:
  1. Extract `t` (timestamp) and `s` (signature) from the signature header
  2. Create message: timestamp + ”.” + stringified_payload
  3. Generate HMAC-SHA256 with your signing secret
  4. Compare computed signature with received signature
Security Tips:
  • Always verify the signature before processing
  • Check timestamp is recent (within 5 minutes recommended)
  • Store `signing_secret` securely, never expose in client-side code
  • Implement idempotency using event `id` to handle retries

Common Transaction Data Fields

All transaction payloads include these core fields:

Retry Policy

StableStack retries failed webhook deliveries with exponential backoff: Retry Conditions:
  • ✅ Retried: 5xx errors, timeouts, network errors, 408, 429
  • ❌ Not retried: 4xx errors (except 408, 429)
Best Practices:
  1. Respond with 2xx status immediately
  2. Process webhook asynchronously
  3. Use event `id` for idempotency
  4. Implement your own retry logic for downstream failures

Testing Webhooks

Use the dashboard to:
  • Send test events
  • View delivery history
  • Check response logs
  • Verify signature validation
See Webhook Security for testing signature verification.