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

# Sandbox payments flow

> End-to-end guide for simulating deposits in sandbox environments. Create settled deposits for test users without waiting for actual bank transfers.

## Overview

This guide walks you through simulating deposit payments in sandbox environments. Use the test deposit endpoint to create settled deposits for test users immediately, making funds available without waiting for actual bank transfers.

<Warning>
  **Test endpoints are only available in development and staging environments.** They are disabled in production
  for security reasons. Always use the sandbox environment (`api.sandbox.wealthyhood.com`) when working with test
  endpoints.
</Warning>

<Info>
  All endpoints require an M2M bearer token. Test endpoints do not require the `x-user-id` header since they
  operate on test data.
</Info>

### Prerequisites

* API access and M2M credentials
* Sandbox environment access (development or staging)
* A test user with a portfolio (see [User builder flow](/flows/user-builder) flow)

<Info>
  If you need to create a test user first, follow the [User builder flow](/flows/user-builder) flow before
  proceeding with this guide.
</Info>

***

## 1) Create a sandbox deposit

Simulate a deposit payment for the test user. This creates a settled deposit transaction immediately, making funds available without waiting for actual bank transfers.

Use `POST /test/deposits` to create a test deposit. You can specify a bank account in one of three ways:

1. Provide a `bankAccount` object to create a new bank account
2. Provide a `bankAccountId` to use an existing bank account
3. Provide neither to use the user's first bank account (if available)

<CodeGroup>
  ```javascript Node.js theme={null}
  async function createTestDeposit({ token, userId, amount, bankAccountId, bankAccount }) {
    const body = { userId, amount };
    if (bankAccountId) {
      body.bankAccountId = bankAccountId;
    } else if (bankAccount) {
      body.bankAccount = bankAccount;
    }
    
    const res = await fetch(`${BASE}/test/deposits`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${token}`,
        'Content-Type': 'application/json',
        'Accept': 'application/json'
      },
      body: JSON.stringify(body)
    });
    if (!res.ok) {
      const error = await res.json();
      throw new Error(`Failed to create deposit: ${error.message}`);
    }
    const deposit = await res.json();
    return deposit;
  }

  // Example 1: Create a €100 deposit using user's first bank account
  const deposit1 = await createTestDeposit({
    token: 'YOUR_M2M_TOKEN',
    userId: user._id,
    amount: 100.00
  });

  // Example 2: Create a deposit with existing bank account ID
  const deposit2 = await createTestDeposit({
    token: 'YOUR_M2M_TOKEN',
    userId: user._id,
    amount: 100.00,
    bankAccountId: '64f1b2c3d4e5f67890123457'
  });

  // Example 3: Create a deposit with new bank account
  const deposit3 = await createTestDeposit({
    token: 'YOUR_M2M_TOKEN',
    userId: user._id,
    amount: 100.00,
    bankAccount: {
      holderName: 'Account Holder Name',
      iban: 'GR1601101250000000012300695',
      bic: 'ETHNGRAA',
      currency: 'EUR'
    }
  });

  console.log('Deposit created:', deposit1.id);
  console.log('Status:', deposit1.status); // Always "Settled"
  console.log('Amount:', deposit1.amount); // In cents (10000)

  ```

  ```bash cURL theme={null}
  # Create deposit using user's first bank account
  curl -X POST 'https://api.sandbox.wealthyhood.com/test/deposits' \
    -H 'Accept: application/json' \
    -H 'Content-Type: application/json' \
    -H 'Authorization: Bearer YOUR_M2M_TOKEN' \
    -d '{
      "userId": "64f0c51e7fb3fc001234abcd",
      "amount": 100.00
    }'

  # Create deposit with existing bank account ID
  curl -X POST 'https://api.sandbox.wealthyhood.com/test/deposits' \
    -H 'Accept: application/json' \
    -H 'Content-Type: application/json' \
    -H 'Authorization: Bearer YOUR_M2M_TOKEN' \
    -d '{
      "userId": "64f0c51e7fb3fc001234abcd",
      "amount": 100.00,
      "bankAccountId": "64f1b2c3d4e5f67890123457"
    }'

  # Create deposit with new bank account
  curl -X POST 'https://api.sandbox.wealthyhood.com/test/deposits' \
    -H 'Accept: application/json' \
    -H 'Content-Type: application/json' \
    -H 'Authorization: Bearer YOUR_M2M_TOKEN' \
    -d '{
      "userId": "64f0c51e7fb3fc001234abcd",
      "amount": 100.00,
      "bankAccount": {
        "holderName": "Account Holder Name",
        "iban": "GR1601101250000000012300695",
        "bic": "ETHNGRAA",
        "currency": "EUR"
      }
    }'
  ```
</CodeGroup>

<Info>
  The deposit is created with `Settled` status immediately, and the user's cash availability is updated automatically. The deposit uses the user's default currency and is associated with their first portfolio.

  **Bank account handling:** If `bankAccount` is provided, a new bank account will be created (or an existing one will be found and reused). If `bankAccountId` is provided, that specific bank account will be used. If neither is provided, the user's first bank account will be used (if available). If the user has no bank accounts and neither `bankAccount` nor `bankAccountId` is provided, the request will fail with a 400 error.
</Info>

<Warning>
  **Requirements**: The user must exist and have a portfolio. If the user has no bank accounts, you must provide
  either `bankAccount` or `bankAccountId` in the request.
</Warning>

***

## 2) Verify the deposit

Verify that the deposit was created successfully and check the user's cash balance.

Use `GET /cash` to check the user's cash balance:

<CodeGroup>
  ```javascript Node.js theme={null}
  async function getCash({ token, userId }) {
    const res = await fetch(`${BASE}/cash`, {
      headers: {
        'Authorization': `Bearer ${token}`,
        'x-user-id': userId,
        'Accept': 'application/json'
      }
    });
    if (!res.ok) throw new Error(`Failed to get cash: ${res.status}`);
    return res.json();
  }

  // Check cash balance after deposit
  const cash = await getCash({
    token: 'YOUR_M2M_TOKEN',
    userId: user._id
  });

  console.log('Available cash:', cash.available);
  console.log('Currency:', cash.currency);

  ```

  ```bash cURL theme={null}
  curl -X GET 'https://api.sandbox.wealthyhood.com/cash' \
    -H 'Accept: application/json' \
    -H 'Authorization: Bearer YOUR_M2M_TOKEN' \
    -H 'x-user-id: 64f0c51e7fb3fc001234abcd'
  ```
</CodeGroup>

Alternatively, use `GET /deposits` to list all deposits for the user:

```bash theme={null}
curl -X GET 'https://api.sandbox.wealthyhood.com/deposits' \
  -H 'Accept: application/json' \
  -H 'Authorization: Bearer YOUR_M2M_TOKEN' \
  -H 'x-user-id: 64f0c51e7fb3fc001234abcd'
```

***

## Troubleshooting

### User not found error

**Error**: `404 - User not found`

**Solution**: Ensure the `userId` is a valid MongoDB ObjectId (24-character hexadecimal string) and the user exists in the system.

### User does not have a portfolio

**Error**: `400 - User does not have a portfolio`

**Solution**: Create the user with a status that includes a portfolio (e.g., `INVESTED`, `INVESTED_WITH_CASH`, `INVESTED_WITH_SAVINGS`). Some statuses may not have portfolios.

### Invalid amount

**Error**: `400 - Amount must be at least 0.01`

**Solution**: Ensure the amount is a positive number greater than or equal to 0.01. Use decimal format (e.g., `100.50`) for amounts with cents.

### Bank account not found

**Error**: `400 - Bank account not found for user`

**Solution**: This occurs when `bankAccountId` is provided but the bank account doesn't exist or doesn't belong to the specified user. Verify the `bankAccountId` is correct and belongs to the user.

### User does not have a bank account

**Error**: `400 - User does not have a bank account. Please provide bankAccount or bankAccountId`

**Solution**: The user has no existing bank accounts. Provide either a `bankAccount` object to create a new bank account, or ensure the user has at least one bank account before making the request.

### Cannot provide both bankAccountId and bankAccount

**Error**: `400 - Cannot provide both bankAccountId and bankAccount`

**Solution**: Provide only one of `bankAccountId` or `bankAccount`, not both.

### Invalid IBAN format

**Error**: `400 - Invalid IBAN format`

**Solution**: Ensure the `bankAccount.iban` field matches the IBAN format specification (e.g., `GR1601101250000000012300695`).

### Invalid currency

**Error**: `400 - Invalid currency`

**Solution**: Ensure `bankAccount.currency` is one of the supported currencies: `EUR`, `GBP`, or `USD`.

### Endpoint not available

**Error**: `403 - Forbidden` or endpoint returns 404

**Solution**: Verify you're using the sandbox environment (`api.sandbox.wealthyhood.com`). Test endpoints are disabled in production.

```
```
