GuidesAPI ReferenceChangelog
API Reference

Webhooks

Webhook events notify your application when specific actions occur in your 1Money account. Your endpoint must respond with a 2xx status code within 10 seconds.

Webhook Events

Detailed onboarding-specific payload guidance is documented separately for Business Onboarding Webhooks and Individual Onboarding Webhooks.

CategoryEvent NameDescription
Business Onboardingaccount.business.readyThe business sub-account has passed compliance review and is ready for use.
account.business.rejectedThe business sub-account has been rejected during compliance review and cannot be activated.
account.business.under_reviewThe business sub-account is under manual compliance review.
account.business.rfiCompliance review has identified issues that require partner action before the account can proceed.
Individual Onboardingaccount.individual.readyThe individual account has passed review and is ready for use.
account.individual.rejectedThe individual account has been rejected during review and cannot be activated.
account.individual.under_reviewThe individual account is under manual compliance review.
account.individual.rfiReview has identified issues that require partner action before the account can proceed.
account.individual.reviewedThe individual account's reviewed tier or limits have changed.
Depositsdeposit.pendingDeposit transaction is pending
deposit.completedDeposit successfully credited to account
deposit.failedDeposit transaction failed
deposit.reversedCompleted deposit was reversed
Crypto Deposit Addressdeposit_instruction.readyDeposit wallet address provisioned and ready for use
deposit_instruction.failedDeposit wallet address provisioning failed
Withdrawalswithdrawal.completedWithdrawal successfully processed
withdrawal.failedWithdrawal transaction failed
withdrawal.returnedWithdrawal was returned by the receiving bank
Internal Transferstransfer.completedInternal transfer completed successfully
Recipientsrecipient.approvedRecipient has been approved by compliance review
recipient.rejectedRecipient has been rejected by compliance review
External Accountsexternal_account.approvedExternal account verified and approved
external_account.failedExternal account verification failed
Conversionsconversion.completedConversion executed successfully
conversion.failedConversion transaction failed
Auto-Conversion Rulesauto_conversion_rule.createAuto-conversion rule creation result (SUCCESS or FAILED)
auto_conversion_rule_order.completedFull conversion flow completed
auto_conversion_rule_order.deposit_failedFailed at deposit stage
auto_conversion_rule_order.conversion_failedFailed at conversion stage
auto_conversion_rule_order.withdrawal_failedFailed at withdrawal stage

HTTP Headers

All webhook requests include the following headers:

HeaderDescriptionExample
Content-TypeRequest content typeapplication/json
X-Webhook-SignatureHMAC-SHA256 signaturea1b2c3d4e5f6... (64 chars)
X-Webhook-TimestampUnix timestamp (seconds)1705920000
X-Webhook-Event-IdUnique event ID12345
X-Webhook-Event-NameEvent typedeposit.completed
X-Webhook-Delivery-IdDelivery attempt ID67890

Signature Verification

To verify webhook authenticity, compute the HMAC-SHA256 signature and compare it with X-Webhook-Signature.

Algorithm

signed_payload = "{timestamp}.{request_body}"
expected_signature = HMAC-SHA256(signed_payload, webhook_secret)

Verification Steps

  1. Extract X-Webhook-Signature and X-Webhook-Timestamp from headers
  2. Concatenate: {timestamp}.{raw_request_body}
  3. Compute HMAC-SHA256 using your webhook secret
  4. Compare signatures using constant-time comparison
  5. Reject if timestamp is older than 5 minutes (replay attack prevention)

Code Example (Node.js)

const crypto = require('crypto');

function verifyWebhookSignature(payload, signature, timestamp, secret) {
  // Check timestamp (5 minute tolerance)
  const now = Math.floor(Date.now() / 1000);
  if (Math.abs(now - timestamp) > 300) {
    return false;
  }

  // Compute expected signature
  const signedPayload = `${timestamp}.${payload}`;
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(signedPayload)
    .digest('hex');

  // Constant-time comparison
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expectedSignature)
  );
}

Code Example (Python)

import hmac
import hashlib
import time

def verify_webhook_signature(payload: str, signature: str, timestamp: int, secret: str) -> bool:
    # Check timestamp (5 minute tolerance)
    now = int(time.time())
    if abs(now - timestamp) > 300:
        return False

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

    # Constant-time comparison
    return hmac.compare_digest(signature, expected_signature)

Payload Structure

All webhook payloads follow this structure:

{
  "event_name": "event.type",
  "resource": {
    "type": "resource_type",
    "id": "resource_id",
    "idempotency_key": "client_passed_idempotency_key"
  },
  "data": {
    // Event-specific data
  }
}

Retry Policy

If your endpoint does not respond with a 2xx status code, we will retry the webhook delivery:

RetryDelay
1st~30 minutes
2nd~1 hour
3rd~2 hours
4th~4 hours
5th~8 hours

After 5 failed attempts (approximately 15.5 hours total), the webhook is marked as permanently failed

Best Practices

  1. Respond quickly - Return 200 OK immediately, process asynchronously
  2. Verify signatures - Always validate X-Webhook-Signature before processing
  3. Handle duplicates - Use X-Webhook-Event-Id for idempotency
  4. Use HTTPS - Webhook endpoints must use HTTPS
  5. Log deliveries - Track X-Webhook-Delivery-Id for debugging