Welcome to the Rise B2B API! This guide will help you migrate from the V1 API to our new, more powerful B2B API. The B2B API introduces significant improvements in security, functionality, and developer experience.

πŸ” Enhanced Security

SIWE authentication replaces X-Auth-Token for better security

⚑ Better Performance

Optimized endpoints with improved response times

🌐 Web3 Native

Built for blockchain with EIP-712 typed data signing

πŸ“Š Improved Data

Enhanced response formats with better error handling

Key Changes Overview

Authentication Changes

  • V1: Used SIWE authentication with /v1/api/siwe endpoints
  • B2B: Uses Sign-In with Ethereum (SIWE) with /v2/auth/siwe endpoints
  • JWT Tokens: Still used but obtained through updated SIWE flow

Endpoint Structure

  • V1: Used /v1/ prefix with various endpoint patterns
  • B2B: Uses /v2/ prefix with consistent REST patterns
  • Base URL: Updated to use the new B2B API URLs - see Environments for API URLs

Data Formats

  • V1: Mixed response formats and error structures
  • B2B: Consistent { success: boolean, data: any } response format
  • Error Handling: Standardized HTTP status codes with detailed error messages

Endpoint Migration Table

Authentication Endpoints

V1 EndpointB2B Endpoint
GET /v1/api/siweGET /v2/auth/siwe
POST /v1/api/siwePOST /v2/auth/verify

Team Management

V1 EndpointB2B Endpoint
GET /v1/teamsGET /v2/user/teams
GET /v1/teams/{teamId}/talentGET /v2/teams/{team_nanoid}/users
GET /v1/teams/{teamId}/talent/{talentId}GET /v2/teams/{team_nanoid}/member/{user_nanoid}/summary
DELETE /v1/teams/{teamId}/talent/{talentId}DELETE /v2/teams/{team_nanoid}/member/{user_nanoid}

Payment Processing

V1 EndpointB2B Endpoint
POST /v1/payments/payPOST /v2/payments + PUT /v2/payments
PUT /v1/payments/payPOST /v2/payments + PUT /v2/payments
POST /v1/payments/batch-payPOST /v2/payments + PUT /v2/payments
PUT /v1/payments/batch-payPOST /v2/payments + PUT /v2/payments
POST /v1/payments/batch-pay/intentsPOST /v2/payments + PUT /v2/payments
GET /v1/payments/GET /v2/payments

Balance Management

V1 EndpointB2B Endpoint
GET /v1/riseid/{rise_id}/balanceGET /v2/balance?nanoid={nanoid}

Invites Management

V1 EndpointB2B Endpoint
GET /v1/invites/GET /v2/invites
POST /v1/invites/ (employees/contractors)POST /v2/invites
POST /v1/invites/ (managers)POST /v2/invites/manager + PUT /v2/invites/manager
POST /v1/invites/warmedPOST /v2/invites

New B2B API Endpoints (Not in V1)

The B2B API introduces several new endpoints that weren’t available in V1:

Team Management (Enhanced)

  • GET /v2/teams/{team_nanoid}/settings - Get team settings
  • PUT /v2/teams/{team_nanoid}/settings - Update team settings
  • GET /v2/teams/{team_nanoid} - Get team by nanoid
  • DELETE /v2/teams/{team_nanoid} - Delete team by nanoid
  • PUT /v2/teams/{team_nanoid} - Update team by nanoid
  • POST /v2/teams - Create a team
  • GET /v2/teams/{team_nanoid}/member/{user_nanoid}/settings - Get member settings
  • PUT /v2/teams/{team_nanoid}/member/{user_nanoid}/settings - Update member settings

Authentication Migration

B2B Authentication (New)

// B2B: SIWE authentication flow
class RiseAuth {
  constructor(baseUrl) {
    this.baseUrl = baseUrl;
  }

  async authenticate(walletAddress, privateKey, riseId) {
    // Step 1: Get SIWE message
    const siweResponse = await fetch(
      `${this.baseUrl}/v2/auth/siwe?wallet=${walletAddress}&riseid=${riseId}`
    );
    const { siwe } = siweResponse.data.data;

    // Step 2: Sign with wallet
    const wallet = new ethers.Wallet(privateKey);
    const signature = await wallet.signMessage(siwe);

    // Extract nonce from SIWE message
    const nonceMatch = siwe.match(/Nonce: (.+)/);
    const nonce = nonceMatch ? nonceMatch[1] : '';

    // Step 3: Verify and get JWT
    const verifyResponse = await fetch(`${this.baseUrl}/v2/auth/verify`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ message: siwe, sig: signature, nonce })
    });

    const { jwt } = verifyResponse.data.data;
    return jwt;
  }
}

// Use JWT in requests (same as V1)
const apiResponse = await fetch(`${this.baseUrl}/v2/teams`, {
  headers: { 'Authorization': `Bearer ${jwt}` }
});

Data Format Changes

Response Format

B2B Response:
{
  "success": true,
  "data": {
    "teams": [
      {
        "nanoid": "te-abc123def456",
        "name": "Engineering Team",
        "created_at": "2024-01-01T00:00:00Z"
      }
    ]
  }
}

Error Format

B2B Error:
{
  "success": false,
  "data": "Team te-abc123def456 not found"
}

ID System Changes

V1: Mixed ID System

  • Teams: 123, 456, 789 (numeric IDs)
  • Users: talentId (numeric IDs)
  • RiseID: rise_id (string format)

B2B: Nanoid System

  • Teams: te-abc123def456
  • Users: us-ghi789jkl012
  • Companies: co-def456ghi789
  • Payments: pa-pay123def456

Migration Checklist

Phase 1: Preparation

  • Review new authentication flow - Update SIWE authentication paths
  • Update base URL - Change to new B2B API URLs (see Environments)
  • Update endpoint paths - Change from /v1/ to /v2/
  • Test authentication - Verify updated SIWE flow works

Phase 2: Core Migration

  • Update team endpoints - Replace numeric IDs with nanoids
  • Update user endpoints - Replace numeric IDs with nanoids
  • Update balance endpoints - Use new query parameter format
  • Update response handling - Handle new { success, data } format

Phase 3: Advanced Features

  • Implement EIP-712 signing - For payments and team management
  • Update error handling - Handle new error format
  • Test all endpoints - Verify functionality works as expected
  • Update documentation - Update internal API documentation

Code Migration Examples

Team Member Retrieval

V1 Code:
const getTeamMembers = async (teamId) => {
  const response = await fetch(`${this.baseUrl}/v1/teams/${teamId}/talent`, {
    headers: { 'Authorization': `Bearer ${jwt}` }
  });
  
  const members = await response.json();
  return members; // Returns array of members
};
B2B Code:
const getTeamMembers = async (teamNanoid) => {
  const response = await fetch(`${this.baseUrl}/v2/teams/${teamNanoid}/users`, {
    headers: { 'Authorization': `Bearer ${jwt}` }
  });
  
  const result = await response.json();
  return result.data.users; // Returns array of users
};

Payment Processing

V1 Code:
const payV1 = async (teamId, recipients, token) => {
  const response = await fetch(`${this.baseUrl}/v1/payments/pay`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      team_id: teamId,
      recipients: recipients.map(r => ({
        user_id: r.userId,
        amount: r.amount,
        currency: r.currency,
        description: r.description
      }))
    })
  });
  return await response.json();
};
B2B Code:
import { ethers } from 'ethers';

async function createPayment(teamNanoid, recipients, walletAddress, privateKey, payNow = true) {
  // Step 1: Create payment draft
  const createResponse = await fetch(`${this.baseUrl}/v2/payments`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${jwt}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      from: teamNanoid,
      to: recipients,
      pay_now: payNow, // true = pay immediately, false = intent (pay later)
      network: 'arbitrum'
    })
  });

  if (!createResponse.ok) {
    const errorText = await createResponse.text();
    throw new Error(`Failed to create payment draft: ${createResponse.status} - ${errorText}`);
  }

  const { data: typedData } = await createResponse.json();
  console.log('βœ… Payment draft created:', typedData);

  // Step 2: Sign typed data
  const wallet = new ethers.Wallet(privateKey);
  const signature = await wallet.signTypedData(
    typedData.domain,
    typedData.types,
    typedData.typed_data
  );

  // Step 3: Execute payment
  const executeResponse = await fetch(`${this.baseUrl}/v2/payments`, {
    method: 'PUT',
    headers: {
      'Authorization': `Bearer ${jwt}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      signer: walletAddress,
      from: teamNanoid,
      to: recipients,
      pay_now: payNow,
      typed_data: typedData.typed_data,
      signature: signature
    })
  });

  const response = await executeResponse.json();
  console.log('βœ… Payment executed:', response.data);
  return response.data;
}

// Usage example
const to = [
  {
    to: 'us-jRxg2LRL54DJ',
    amount_cents: 300,
    currency_symbol: 'USD',
    invoice_description: 'Papa Sent you',
  },
  {
    to: 'us-d6JHBF2kuZjE',
    amount_cents: 700,
    currency_symbol: 'USD',
    invoice_description: 'Papa Sent you',
  },
];

const payment = await createPayment(
  'te-bXy7gjb_Iga-',
  to,
  '<WALLET_ADDRESS>',
  '<WALLET_PRIVATE_KEY>',
  true // true = pay immediately, false = pay intent (pay later)
);
Use pay_now: true to execute payments immediately, or pay_now: false to create a payment intent for later execution.

Balance Retrieval

B2B Code:
const getBalance = async (nanoid) => {
  const response = await fetch(`${this.baseUrl}/v2/balance?nanoid=${nanoid}`, {
    headers: { 'Authorization': `Bearer ${jwt}` }
  });
  
  const result = await response.json();
  return result.data; // Returns balance with account address and currency breakdown
};

Common Migration Issues

Issue 1: Authentication Errors

Problem: Getting 401 errors after migration Solution:
  • Update SIWE endpoint paths from /v1/api/siwe to /v2/auth/siwe and /v2/auth/verify
  • Check that JWT tokens are included as Authorization: Bearer <jwt> headers
  • Verify JWT hasn’t expired (24-hour lifetime)

Issue 2: ID Format Errors

Problem: Getting 404 errors for resources that should exist Solution:
  • Replace numeric IDs with nanoids
  • Update all endpoint URLs to use nanoid format
  • Check that you’re using the correct nanoid type (team, user, company)

Issue 3: Response Format Errors

Problem: Code expecting old response format Solution:
  • Update response handling to use response.data.data instead of direct properties
  • Handle the new { success, data } wrapper format
  • Update error handling to use response.data for error messages

Issue 4: Missing EIP-712 Signing

Problem: Getting errors about missing signatures Solution:
  • Implement EIP-712 typed data signing for operations that require it
  • Use the two-step process (create + execute) for payments and team management
  • Ensure wallet is connected and has proper permissions

Support During Migration

Need Help? Our support team is available to help with your migration. Contact us at Hello@Riseworks.io for personalized assistance.
Important: The V1 API will be deprecated in the future. We recommend completing your migration as soon as possible to ensure continued access to Rise services.