> ## Documentation Index
> Fetch the complete documentation index at: https://docs.riseworks.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Migration Guide

> Upgrading from Rise Webhooks v1 to v2

<Warning>
  **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.
</Warning>

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.

<Note>
  **SDK Required**: For v2 webhook handling, you'll need to install the Rise SDK: `npm install @riseworks/riseworks-sdk` (or `yarn add @riseworks/riseworks-sdk` / `pnpm add @riseworks/riseworks-sdk`)
</Note>

## Understanding the changes

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

<CardGroup cols={2}>
  <Card title="Structured envelope" icon="envelope">
    v2 uses a consistent envelope format for all events with enhanced metadata
  </Card>

  <Card title="Nanoid identifiers" icon="fingerprint">
    Replaced numeric IDs with human-readable nanoids for better tracking
  </Card>

  <Card title="Versioning support" icon="code-branch">
    Each event includes version information for future compatibility
  </Card>

  <Card title="Enhanced security" icon="shield">
    HMAC-based signature verification with individual customer secrets
  </Card>
</CardGroup>

### Webhook payload structure

<Tabs>
  <Tab title="v1 (Deprecated)">
    <Warning>Will be discontinued: This structure will no longer be available after v1 deprecation.</Warning>

    ```json theme={null}
    {
      "type": "deposit.deposit_received",
      "idempotent_key": "0x012321",
      "company_id": 1,
      "timestamp": 1700242816,
      "transaction": {
        // Event-specific data
      }
    }
    ```
  </Tab>

  <Tab title="v2 (Current)">
    ```json theme={null}
    {
      "object": "event",
      "created": 1751590453,
      "request_id": "req-1751590452487",
      "event_type": "payment.sent",
      "event_version": "2.0",
      "idempotency_key": "85420805-0b5e-4b11-b7f4-c6f05db7120b",
      // Event-specific data structure
    }
    ```
  </Tab>
</Tabs>

## Security model changes

### v1 security (deprecated)

<Warning>Deprecated: v1 security model will be discontinued with v1 deprecation.</Warning>

v1 used a public key verification system:

```javascript v1 verification (DEPRECATED) theme={null}
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:

```javascript v2 verification with SDK (CURRENT) theme={null}
const { WebhookValidator } = require('@riseworks/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**

```javascript v2 safe verification with SDK theme={null}
const { WebhookValidator } = require('@riseworks/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;
}
```

**Alternative: Safe validation with error handling**

```javascript v2 safe verification with SDK theme={null}
const { WebhookValidator } = require('@riseworks/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;
}
```

<CardGroup cols={3}>
  <Card title="Individual secrets" icon="key">
    Each customer manages their own webhook secret
  </Card>

  <Card title="Replay protection" icon="clock">
    Timestamps prevent old events from being replayed
  </Card>

  <Card title="HMAC verification" icon="shield">
    Industry-standard signature method
  </Card>
</CardGroup>

## Event type mapping

<Warning>
  Important: All v1 event types listed below will be discontinued when v1 is deprecated. Ensure you update your integration to handle v2 event types.
</Warning>

| v1 Event Type                        | v2 Event Type                          | Changes                             |
| ------------------------------------ | -------------------------------------- | ----------------------------------- |
| `deposit.deposit_received`           | `deposit.received`                     | Simplified naming, enhanced payload |
| `payment.payment_sent`               | `payment.sent`                         | Cleaner naming, structured data     |
| `pay_schedules.pay_schedule_created` | `payment.group.created`                | Renamed to reflect payment groups   |
| `invites.invite_accepted`            | `invite.accepted`                      | Simplified naming                   |
| `account_duplicated.detected`        | `withdraw_account.duplicated_detected` | More specific naming                |
| `payee.riseid_address_updated`       | *(Deprecated)*                         | No longer supported in v2           |

## Recommended migration strategy

<Info>
  **Migration Required**: Since v1 will be deprecated, migration to v2 is mandatory, not optional.
</Info>

We recommend the **gradual migration approach** to minimize risk and ensure a smooth transition:

<Steps>
  <Step title="Set up parallel webhooks">
    Support both v1 and v2 webhooks during the transition period:

    ```javascript theme={null}
    // 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/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;
    }
    ```
  </Step>

  <Step title="Update event processing">
    Create a single event processor that handles both formats:

    ```javascript theme={null}
    function processWebhookEvent(event) {
      // Your unified event processing logic here
      // Handle both v1 and v2 event formats
    }
    ```
  </Step>

  <Step title="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
  </Step>

  <Step title="Monitor both endpoints">
    Run both webhooks in parallel while tracking migration progress:

    ```javascript theme={null}
    // 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/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
    ```
  </Step>

  <Step title="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
  </Step>
</Steps>

## Migration checklist

<Info>
  **Time-Sensitive**: Complete migration before v1 deprecation date to avoid service disruption.
</Info>

<AccordionGroup>
  <Accordion title="Pre-migration">
    * 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
  </Accordion>

  <Accordion title="During migration">
    * 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
  </Accordion>

  <Accordion title="Post-migration">
    * 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
  </Accordion>
</AccordionGroup>

## Getting help with migration

If you encounter issues during migration:

<CardGroup cols={2}>
  <Card title="Troubleshooting guide" icon="wrench" href="/webhooks/operations/troubleshooting">
    Common migration problems and solutions
  </Card>

  <Card title="Delivery history" icon="arrow-rotate-left">
    Use your Rise dashboard to check webhook delivery status
  </Card>

  <Card title="Incremental testing" icon="flask">
    Migrate one event type at a time for safer deployment
  </Card>

  <Card title="Contact support" icon="headphones">
    Our support team can assist with complex migrations
  </Card>
</CardGroup>

## What's next?

After completing your migration to v2:

<CardGroup cols={2}>
  <Card title="Monitor webhooks" icon="chart-line" href="/webhooks/operations/monitoring">
    Track v2 delivery and webhook health
  </Card>

  <Card title="Optimize delivery" icon="rocket" href="/webhooks/operations/delivery">
    Take advantage of v2 features and improvements
  </Card>

  <Card title="Explore new features" icon="star" href="/webhooks/implementation/event-types">
    Use enhanced event data and new event types
  </Card>

  <Card title="Event Reference" icon="book" href="/webhooks/implementation/event-types">
    Complete v2 event types and payload documentation
  </Card>
</CardGroup>

<Tip>
  **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.
</Tip>

<Warning>
  **Important reminder**: v1 webhooks will be discontinued on **\[DATE]**. Ensure your migration is complete before this date to avoid service interruption.
</Warning>
