> ## 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.

# Payments

> Understand payment flows and security in Rise B2B API

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:

<CardGroup cols={2}>
  <Card title="Individual Payments" icon="user">
    Single payments to one recipient
  </Card>

  <Card title="Batch Payments" icon="users">
    Multiple payments to multiple recipients in one transaction
  </Card>
</CardGroup>

## Payment Flow

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

<Steps>
  <Step title="Create Payment">
    Create payment and get typed data using POST /v2/payments
  </Step>

  <Step title="Sign with Wallet">
    Sign the typed data using your Web3 wallet
  </Step>

  <Step title="Execute Payment">
    Submit the signed data using PUT /v2/payments to execute on-chain
  </Step>
</Steps>

## Payment Security

<CardGroup cols={2}>
  <Card title="On-Chain Verification" icon="shield">
    All payments are verified and executed on the blockchain
  </Card>

  <Card title="Typed Data Signing" icon="file-lines">
    EIP-712 signatures prevent tampering and replay attacks
  </Card>

  <Card title="HTTPS Required" icon="lock">
    All API communications use encrypted HTTPS
  </Card>

  <Card title="Contract Validation" icon="circle-check">
    Verify contract addresses and chain IDs
  </Card>
</CardGroup>

## API Endpoints

### 1. Create Payment

**POST** `${this.baseUrl}/v2/payments`

Creates a payment and returns EIP-712 typed data for signing.

<RequestExample>
  ```bash theme={null}
  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"
    }'
  ```
</RequestExample>

<ResponseExample>
  ```json theme={null}
  {
    "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"
    }
  }
  ```
</ResponseExample>

### 2. Execute Payment

**PUT** `${this.baseUrl}/v2/payments`

Executes the payment using signed typed data.

<RequestExample>
  ```bash theme={null}
  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..."
    }'
  ```
</RequestExample>

<ResponseExample>
  ```json theme={null}
  {
    "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..."
        }
      ]
    }
  }
  ```
</ResponseExample>

### 3. Query Payments

**GET** `${this.baseUrl}/v2/payments`

Query payments for a team with optional filtering.

<RequestExample>
  ```bash theme={null}
  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"
  ```
</RequestExample>

## API Integration Example

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

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

### Query Parameters

| Parameter     | Type   | Required | Description                                                     |
| ------------- | ------ | -------- | --------------------------------------------------------------- |
| `team_nanoid` | string | Yes      | Team identifier                                                 |
| `state`       | string | No       | Payment state filter (`all`, `intent`, `scheduled`, `complete`) |
| `query_type`  | string | Yes      | Query type (`payable`, `receivable`)                            |
| `start_date`  | string | No       | Start date for filtering (YYYY-MM-DD)                           |
| `end_date`    | string | No       | End date for filtering (YYYY-MM-DD)                             |
| `recipient`   | string | No       | Filter by specific recipient                                    |

## Payment Timing

Rise supports two payment timing options:

| Option           | Description                  | Use Case                           |
| ---------------- | ---------------------------- | ---------------------------------- |
| `pay_now: true`  | Payment executes immediately | Instant payroll, urgent payments   |
| `pay_now: false` | Payment intent (scheduled)   | Future payroll, scheduled payments |

## Payment States

Payments go through several states during processing:

| State       | Description                     | Next Actions               |
| ----------- | ------------------------------- | -------------------------- |
| `intent`    | Payment intent created          | Sign and execute           |
| `scheduled` | Payment scheduled for future    | Wait for execution time    |
| `complete`  | Payment completed on blockchain | Payment successful         |
| `removed`   | Payment cancelled or failed     | Review and retry if needed |

## Error Handling

Common payment errors and solutions:

| Error                          | Description                          | Solution                         |
| ------------------------------ | ------------------------------------ | -------------------------------- |
| `INSUFFICIENT_BALANCE`         | Not enough funds in entity balance   | Add funds to the entity balance  |
| `INVALID_SIGNATURE`            | Signature verification failed        | Ensure correct wallet is signing |
| `EXPIRED_TYPED_DATA`           | Typed data has expired               | Request fresh typed data         |
| `INVALID_RECIPIENT`            | Recipient address is invalid         | Verify recipient nanoid exists   |
| `TEAM_ROLE_SETTINGS_NOT_FOUND` | User not properly configured in team | Check team role settings         |

## Best Practices

<Warning>
  **Always review payment details before signing** to prevent unauthorized transactions.
</Warning>

* **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

## Related Resources

<CardGroup cols={2}>
  <Card title="Payment Integration Guide" icon="code" href="/guides/payment-integration">
    Complete payment integration examples
  </Card>

  <Card title="Web3 Integration" icon="wallet" href="/web3-integration">
    Wallet integration and signing
  </Card>

  <Card title="Entity Balance" icon="wallet" href="/concepts/entity-balance">
    Managing entity balances
  </Card>

  <Card title="Teams" icon="users" href="/concepts/teams">
    Team payment permissions
  </Card>
</CardGroup>

<Note>
  **Payment Precision**: All payment amounts are specified in cents to maintain precision. Convert to decimal format only when displaying to users.
</Note>
