Skip to main content
Important: Rise Webhooks v1 is deprecated and will be discontinued. All customers must migrate to v2 by [DATE]. After this date, v1 webhooks will no longer be supported.
Rise Webhooks v2 introduces new features and enhancements in reliability, security, and event structure. This guide helps you migrate from v1 to the new v2 architecture.
SDK Required: For v2 webhook handling, you’ll need to install the Rise SDK: npm install @riseworks/sdk

Understanding the changes

The migration from v1 to v2 involves fundamental changes to webhook structure, security, and event types.

Structured envelope

v2 uses a consistent envelope format for all events with enhanced metadata

Nanoid identifiers

Replaced numeric IDs with human-readable nanoids for better tracking

Versioning support

Each event includes version information for future compatibility

Enhanced security

HMAC-based signature verification with individual customer secrets

Webhook payload structure

  • v1 (Deprecated)
  • v2 (Current)
Will be discontinued: This structure will no longer be available after v1 deprecation.
{
  "type": "deposit.deposit_received",
  "idempotent_key": "0x012321",
  "company_id": 1,
  "timestamp": 1700242816,
  "transaction": {
    // Event-specific data
  }
}

Security model changes

v1 security (deprecated)

Deprecated: v1 security model will be discontinued with v1 deprecation.
v1 used a public key verification system:
v1 verification (DEPRECATED)
const hash = req.headers['x-rise-hash'];
const signature = req.headers['x-rise-signature'];

// Verify hash
const bodyHash = ethers.id(JSON.stringify(body));
if (bodyHash !== hash) {
  return res.status(400).send('Invalid hash');
}

// Verify signature with the public key from your dashboard
const riseSigner = '0x1234'; // Public key from your Rise dashboard
const recoveredAddress = ethers.verifyMessage(hash, signature);
if (recoveredAddress !== riseSigner) {
  return res.status(400).send('Invalid signature');
}

v2 security (current)

v2 uses HMAC-based signature verification with your own secret. The Rise SDK provides built-in webhook validation:
v2 verification with SDK (CURRENT)
const { WebhookValidator } = require('@riseworks/sdk');

// Initialize webhook validator with your secret
const validator = new WebhookValidator({
  secret: process.env.RISE_WEBHOOK_SECRET,
  tolerance: 300 // 5 minutes tolerance for timestamp validation
});

// Verify signature and get validated event
const event = validator.validateEvent(req.body, req.headers['x-rise-signature']);
console.log('Validated event:', event);
Alternative: Safe validation with error handling
v2 safe verification with SDK
const { WebhookValidator } = require('@riseworks/sdk');

const validator = new WebhookValidator({
  secret: process.env.RISE_WEBHOOK_SECRET,
  tolerance: 300
});

try {
  // Safe validation that returns null on failure instead of throwing
  const event = validator.validateEventSafe(req.body, req.headers['x-rise-signature']);
  
  if (event) {
    console.log('Validated event:', event);
    // Process the event
  } else {
    console.error('Invalid webhook signature');
    res.status(400).send('Invalid signature');
    return;
  }
} catch (error) {
  console.error('Webhook validation error:', error.message);
  res.status(400).send('Validation failed');
  return;
}

Individual secrets

Each customer manages their own webhook secret

Replay protection

Timestamps prevent old events from being replayed

HMAC verification

Industry-standard signature method

Event type mapping

Important: All v1 event types listed below will be discontinued when v1 is deprecated. Ensure you update your integration to handle v2 event types.
v1 Event Typev2 Event TypeChanges
deposit.deposit_receiveddeposit.receivedSimplified naming, enhanced payload
payment.payment_sentpayment.sentCleaner naming, structured data
pay_schedules.pay_schedule_createdpayment.group.createdRenamed to reflect payment groups
invites.invite_acceptedinvite.acceptedSimplified naming
account_duplicated.detectedwithdraw_account.duplicated_detectedMore specific naming
payee.riseid_address_updated(Deprecated)No longer supported in v2
Migration Required: Since v1 will be deprecated, migration to v2 is mandatory, not optional.
We recommend the gradual migration approach to minimize risk and ensure a smooth transition:
1

Set up parallel webhooks

Support both v1 and v2 webhooks during the transition period:
// Support both v1 and v2 webhooks during transition
app.post('/webhooks/v1', handleV1Webhook);
app.post('/webhooks/v2', handleV2Webhook);

function handleV1Webhook(req, res) {
  // Existing v1 logic with v1 signature verification
  const hash = req.headers['x-rise-hash'];
  const signature = req.headers['x-rise-signature'];

  // v1 verification (keep existing logic)
  verifyV1Signature(req.body, hash, signature);

  // Convert to v2 format for unified processing
  const v2Event = convertV1ToV2(req.body);
  processWebhookEvent(v2Event);

  res.status(200).send('OK');
}

function handleV2Webhook(req, res) {
  // New v2 logic with SDK
  const { WebhookValidator } = require('@riseworks/sdk');
  
  const validator = new WebhookValidator({
    secret: process.env.RISE_WEBHOOK_SECRET,
    tolerance: 300
  });

  try {
    // Validate webhook signature using SDK
    const event = validator.validateEvent(req.body, req.headers['x-rise-signature']);
    processWebhookEvent(event);
    
    res.status(200).json({ received: true });
  } catch (error) {
    console.error('Webhook validation failed:', error.message);
    res.status(400).send('Invalid signature');
  }
}

// Convert v1 events to v2 format for unified processing
function convertV1ToV2(v1Event) {
  // Your conversion logic here based on event type
  return {
    object: 'event',
    created: v1Event.timestamp,
    request_id: `v1-${v1Event.idempotent_key}`,
    event_type: mapV1ToV2EventType(v1Event.type),
    event_version: '1.0',
    idempotency_key: v1Event.idempotent_key,
    // Map v1 data to v2 structure
    ...v1Event.transaction
  };
}

function mapV1ToV2EventType(v1Type) {
  const mapping = {
    'deposit.deposit_received': 'deposit.received',
    'payment.payment_sent': 'payment.sent',
    'pay_schedules.pay_schedule_created': 'payment.group.created',
    'invites.invite_accepted': 'invite.accepted',
    'account_duplicated.detected': 'withdraw_account.duplicated_detected'
  };
  return mapping[v1Type] || v1Type;
}
2

Update event processing

Create a single event processor that handles both formats:
function processWebhookEvent(event) {
  // Your unified event processing logic here
  // Handle both v1 and v2 event formats
}
3

Create v2 webhook in Rise app

  1. Navigate to webhook settings in the Rise app
  2. Create new webhook with your /webhooks/v2 endpoint
  3. Generate webhook secret and store it securely
  4. Subscribe to same events as your v1 webhook
  5. Test the v2 webhook using Rise’s test feature
4

Monitor both endpoints

Run both webhooks in parallel while tracking migration progress:
// Add monitoring to track migration progress
const migrationStats = {
  v1Count: 0,
  v2Count: 0,
  v1Errors: 0,
  v2Errors: 0
};

function handleV1Webhook(req, res) {
  migrationStats.v1Count++;
  try {
    // Your v1 processing logic here
    const v2Event = convertV1ToV2(req.body);
    processWebhookEvent(v2Event);
    res.status(200).send('OK');
  } catch (error) {
    migrationStats.v1Errors++;
    console.error('V1 webhook error:', error.message);
    res.status(400).send('Error');
  }
}

function handleV2Webhook(req, res) {
  migrationStats.v2Count++;
  try {
    // V2 processing with SDK
    const { WebhookValidator } = require('@riseworks/sdk');
    
    const validator = new WebhookValidator({
      secret: process.env.RISE_WEBHOOK_SECRET,
      tolerance: 300
    });

    const event = validator.validateEvent(req.body, req.headers['x-rise-signature']);
    processWebhookEvent(event);
    
    res.status(200).json({ received: true });
  } catch (error) {
    migrationStats.v2Errors++;
    console.error('V2 webhook error:', error.message);
    res.status(400).send('Invalid signature');
  }
}

// Log stats periodically
setInterval(() => {
  console.log('Migration stats:', migrationStats);
}, 60000); // Every minute
5

Switch to v2 only

Once you’re confident v2 is working correctly:
  1. Deactivate v1 webhook in the Rise app
  2. Monitor v2 webhook for any issues
  3. Remove v1 endpoint from your code after a few days
  4. Clean up migration code once fully migrated

Migration checklist

Time-Sensitive: Complete migration before v1 deprecation date to avoid service disruption.
  • Review v1 webhook usage in your application
  • Identify all event types currently processed
  • Plan migration strategy
  • Set up testing environment
  • Generate webhook secret for v2
  • Implement v2 webhook endpoint
  • Add signature verification for v2
  • Update event processing logic
  • Test both v1 and v2 events during parallel operation
  • Monitor webhook delivery success rates
  • Remove v1 webhook endpoints when no longer needed
  • Update documentation and team knowledge
  • Monitor v2 webhook functionality
  • Remove v1 compatibility code after transition period
  • Update monitoring and alerting for new event types

Getting help with migration

If you encounter issues during migration:

Troubleshooting guide

Common migration problems and solutions

Delivery history

Use your Rise dashboard to check webhook delivery status

Incremental testing

Migrate one event type at a time for safer deployment

Contact support

Our support team can assist with complex migrations

What’s next?

After completing your migration to v2:
Migration tip: Take your time with migration, but don’t delay too long. It’s better to migrate carefully over a few days than to rush and break production systems. The gradual migration approach allows you to validate each step before proceeding.
Important reminder: v1 webhooks will be discontinued on [DATE]. Ensure your migration is complete before this date to avoid service interruption.
I