Skip to main content

Documentation Index

Fetch the complete documentation index at: https://www.smartretry.com/docs/llms.txt

Use this file to discover all available pages before exploring further.

Webhooks let SmartRetry push event notifications to your server in real time. Instead of polling the status endpoint, you receive an HTTP POST request whenever a transaction’s state changes.

How webhooks work

1

Configure your endpoint

Register a webhook URL in your SmartRetry dashboard. This endpoint must be publicly accessible and respond to HTTPS POST requests.
2

Receive events

When a transaction event occurs (approval, decline, retry attempt, etc.), SmartRetry sends a JSON payload to your endpoint.
3

Acknowledge receipt

Return a 2xx status code within 30 seconds to confirm receipt. Any other response triggers a retry.

Event types

EventDescription
transaction.approvedA transaction was approved by the issuer.
transaction.declinedA transaction was declined. Check reason_code for details.
transaction.pendingA transaction is awaiting final status (e.g., 3DS challenge).
transaction.retry_scheduledSmartRetry scheduled an automatic retry for a soft decline.
transaction.retry_attemptedA retry attempt was made.
recurring.createdA new recurring series was initialized.
recurring.chargedA recurring payment was processed.
recurring.cancelledA recurring series was cancelled.
recurring.completedA recurring series reached its payment limit.
future_transaction.scheduledA future payment was scheduled.
future_transaction.executedA scheduled payment was processed.
future_transaction.cancelledA scheduled payment was cancelled.

Webhook payload

All webhook payloads follow a consistent structure:
{
  "id": "evt_8A3F2C1D",
  "type": "transaction.approved",
  "created_at": "2026-04-01T14:22:13Z",
  "data": {
    "transaction_id": "TX8A3F2C",
    "order_id": "OR7B9E1D",
    "merchant_transaction_id": "order-20260331-001",
    "amount": 49.99,
    "currency": "USD",
    "status": {
      "status": "APPROVED",
      "reasonCode": "AUTH.APPROVED",
      "domain": "AUTH"
    }
  }
}
id
string
required
Unique identifier for this webhook event. Use this to deduplicate retried deliveries.
type
string
required
The event type. See Event types above.
created_at
string
required
ISO 8601 timestamp of when the event occurred.
data
object
required
Event-specific payload. Structure varies by event type but always includes relevant IDs.

Verifying webhook signatures

Every webhook request includes a signature header to verify the request originated from SmartRetry.
X-SmartRetry-Signature: t=1711979533,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd
The signature header contains:
  • t - Unix timestamp of when the signature was generated
  • v1 - HMAC-SHA256 signature of the payload

Verification steps

import hmac
import hashlib
import time

def verify_webhook(payload: bytes, signature_header: str, webhook_secret: str) -> bool:
    # Parse the signature header
    parts = dict(part.split("=") for part in signature_header.split(","))
    timestamp = parts["t"]
    expected_signature = parts["v1"]

    # Reject if timestamp is too old (5 minute tolerance)
    if abs(time.time() - int(timestamp)) > 300:
        return False

    # Compute expected signature
    signed_payload = f"{timestamp}.{payload.decode()}"
    computed = hmac.new(
        webhook_secret.encode(),
        signed_payload.encode(),
        hashlib.sha256
    ).hexdigest()

    return hmac.compare_digest(computed, expected_signature)
Always verify webhook signatures before processing events. Never trust the payload without verification.

Retry behavior

If your endpoint doesn’t return a 2xx response, SmartRetry retries the delivery with exponential backoff:
AttemptDelay
1Immediate
21 minute
35 minutes
430 minutes
52 hours
68 hours
724 hours
After 7 failed attempts, the webhook is marked as failed. You can manually retry failed webhooks from the dashboard.
Use the id field to deduplicate webhook deliveries. The same event may be delivered multiple times if your endpoint returned an error or timed out.

Best practices

  1. Respond quickly - Return a 2xx response immediately and process the event asynchronously. If processing takes longer than 30 seconds, the request times out and triggers a retry.
  2. Idempotent handlers - Design your webhook handlers to safely process the same event multiple times. Use the id field as a deduplication key.
  3. Verify signatures - Always validate the X-SmartRetry-Signature header before processing any webhook.
  4. Use HTTPS - Webhook endpoints must use HTTPS. HTTP URLs are rejected.
  5. Handle all event types - Your handler should gracefully ignore event types it doesn’t recognize, allowing for future expansion.

Testing webhooks

In sandbox mode, you can trigger test webhook events from the dashboard:
  1. Navigate to Settings > Webhooks
  2. Click Send test event
  3. Select an event type
  4. Review the payload delivered to your endpoint
Sandbox webhook events include "environment": "sandbox" in the payload to distinguish them from production events.