curl -X POST "${this.baseUrl}/v2/payments" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "te-abc123def456",
    "to": [
      {
        "to": "us-xyz789abc123",
        "amount_cents": 100000,
        "currency_symbol": "USD",
        "invoice_description": "Salary payment for January 2024"
      }
    ],
    "pay_now": true,
    "network": "arbitrum"
  }'
{
  "success": true,
  "data": {
    "domain": {
      "name": "RiseAccountForwarder",
      "version": "1.0.0",
      "chainId": 42161,
      "verifyingContract": "0x..."
    },
    "types": {
      "CreatePaymentsForwardRequest": [...]
    },
    "typed_data": {
      "from": "0x...",
      "to": "0x...",
      "salt": "12345",
      "expires": "1750492712",
      "data": [...]
    },
    "primary_type": "CreatePaymentsForwardRequest"
  }
}
Rise B2B API supports secure, on-chain payments for payroll and business operations. All payments are processed through blockchain transactions with EIP-712 typed data signing for enhanced security.

Payment Types

Rise B2B supports two main payment types:

Individual Payments

Single payments to one recipient

Batch Payments

Multiple payments to multiple recipients in one transaction

Payment Flow

The Rise payment process follows a secure 3-step flow:
1

Create Payment

Create payment and get typed data using POST /v2/payments
2

Sign with Wallet

Sign the typed data using your Web3 wallet
3

Execute Payment

Submit the signed data using PUT /v2/payments to execute on-chain

Payment Security

🔐 On-Chain Verification

All payments are verified and executed on the blockchain

✍️ Typed Data Signing

EIP-712 signatures prevent tampering and replay attacks

🔒 HTTPS Required

All API communications use encrypted HTTPS

✅ Contract Validation

Verify contract addresses and chain IDs

API Endpoints

1. Create Payment

POST ${this.baseUrl}/v2/payments Creates a payment and returns EIP-712 typed data for signing.
curl -X POST "${this.baseUrl}/v2/payments" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "te-abc123def456",
    "to": [
      {
        "to": "us-xyz789abc123",
        "amount_cents": 100000,
        "currency_symbol": "USD",
        "invoice_description": "Salary payment for January 2024"
      }
    ],
    "pay_now": true,
    "network": "arbitrum"
  }'
{
  "success": true,
  "data": {
    "domain": {
      "name": "RiseAccountForwarder",
      "version": "1.0.0",
      "chainId": 42161,
      "verifyingContract": "0x..."
    },
    "types": {
      "CreatePaymentsForwardRequest": [...]
    },
    "typed_data": {
      "from": "0x...",
      "to": "0x...",
      "salt": "12345",
      "expires": "1750492712",
      "data": [...]
    },
    "primary_type": "CreatePaymentsForwardRequest"
  }
}

2. Execute Payment

PUT ${this.baseUrl}/v2/payments Executes the payment using signed typed data.
curl -X PUT "${this.baseUrl}/v2/payments" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "signer": "0x1234567890abcdef...",
    "from": "te-abc123def456",
    "to": [
      {
        "to": "us-xyz789abc123",
        "amount_cents": 100000,
        "currency_symbol": "USD",
        "invoice_description": "Salary payment for January 2024"
      }
    ],
    "pay_now": true,
    "network": "arbitrum",
    "typed_data": {...},
    "signature": "0x..."
  }'
{
  "success": true,
  "data": {
    "transaction": "tx-abc123def456",
    "payments": [
      {
        "id": "pay-xyz789abc123",
        "groupID": "group-123",
        "payAtTime": "1704067200",
        "validMinutes": "1440",
        "payType": "immediate",
        "token": "0x...",
        "recipient": "0x...",
        "amount": "1000000000000000000",
        "data": "0x..."
      }
    ]
  }
}

3. Query Payments

GET ${this.baseUrl}/v2/payments Query payments for a team with optional filtering.
curl -X GET "${this.baseUrl}/v2/payments?team_nanoid=te-abc123def456&state=all&query_type=payable&start_date=2024-01-01&end_date=2024-01-31" \
  -H "Authorization: Bearer YOUR_JWT_TOKEN"

API Integration Example

import { ethers } from 'ethers';

class RisePayments {
  constructor(baseUrl, jwtToken) {
    this.baseUrl = baseUrl;
    this.headers = {
      'Authorization': `Bearer ${jwtToken}`,
      'Content-Type': 'application/json'
    };
  }

  async createPayment(
    teamNanoid,
    recipients,
    walletAddress,
    privateKey,
    payNow = true
  ) {
    // Step 1: Create payment draft
    const createResponse = await fetch(`${this.baseUrl}/v2/payments`, {
      method: 'POST',
      headers: this.headers,
      body: JSON.stringify({
        from: teamNanoid,
        to: recipients,
        pay_now: payNow,
        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: this.headers,
      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;
  }

  async queryPayments(teamNanoid, options = {}) {
    const params = new URLSearchParams({
      team_nanoid: teamNanoid,
      state: options.state || 'all',
      query_type: options.queryType || 'payable',
      ...(options.startDate && { start_date: options.startDate }),
      ...(options.endDate && { end_date: options.endDate }),
      ...(options.recipient && { recipient: options.recipient })
    });
    
    const response = await fetch(`${this.baseUrl}/v2/payments?${params}`, {
      headers: this.headers
    });
    
    return response.json();
  }
}

// Usage example
const paymentsApi = new RisePayments(
  'your-base-url', // Configure for your environment
  'your-jwt-token'
);

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 paymentsApi.createPayment(
  'te-bXy7gjb_Iga-',
  to,
  process.env.WALLET_ADDRESS,
  process.env.WALLET_PRIVATE_KEY,
  true // true = pay immediately, false = pay intent (pay later)
);

Payment Data Structure

Payment Request

{
  "from": "te-abc123def456",
  "to": [
    {
      "to": "us-xyz789abc123",
      "amount_cents": 100000,
      "currency_symbol": "USD",
      "invoice_description": "Optional description"
    }
  ],
  "pay_now": true,
  "network": "arbitrum"
}

Query Parameters

ParameterTypeRequiredDescription
team_nanoidstringYesTeam identifier
statestringNoPayment state filter (all, intent, scheduled, complete)
query_typestringYesQuery type (payable, receivable)
start_datestringNoStart date for filtering (YYYY-MM-DD)
end_datestringNoEnd date for filtering (YYYY-MM-DD)
recipientstringNoFilter by specific recipient

Payment Timing

Rise supports two payment timing options:
OptionDescriptionUse Case
pay_now: truePayment executes immediatelyInstant payroll, urgent payments
pay_now: falsePayment intent (scheduled)Future payroll, scheduled payments

Payment States

Payments go through several states during processing:
StateDescriptionNext Actions
intentPayment intent createdSign and execute
scheduledPayment scheduled for futureWait for execution time
completePayment completed on blockchainPayment successful
removedPayment cancelled or failedReview and retry if needed

Error Handling

Common payment errors and solutions:
ErrorDescriptionSolution
INSUFFICIENT_BALANCENot enough funds in entity balanceAdd funds to the entity balance
INVALID_SIGNATURESignature verification failedEnsure correct wallet is signing
EXPIRED_TYPED_DATATyped data has expiredRequest fresh typed data
INVALID_RECIPIENTRecipient address is invalidVerify recipient nanoid exists
TEAM_ROLE_SETTINGS_NOT_FOUNDUser not properly configured in teamCheck team role settings

Best Practices

Always review payment details before signing to prevent unauthorized transactions.
  • Verify Recipients: Double-check recipient addresses and amounts
  • Monitor Balances: Ensure sufficient funds before creating payments
  • Track Status: Monitor payment status through the query endpoint
  • Handle Errors: Implement proper error handling for failed payments
  • Security: Use HTTPS and verify contract addresses
  • Rate Limiting: Implement appropriate rate limiting for payment queries
  • Wallet Security: Keep private keys secure and never expose them in client-side code
Payment Precision: All payment amounts are specified in cents to maintain precision. Convert to decimal format only when displaying to users.