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

# Wallet Top-Up

> Initiate manual wallet top-ups and manage auto top-up rules via the API.

The Wallet Top-Up API lets you programmatically add funds to a customer's wallet balance by initiating payment collection, and configure automatic top-up rules that trigger when the balance drops below a threshold.

## Manual Top-Up

### Initiate a Top-Up

```bash theme={null}
curl -X POST https://coreapi.io/api/wallet/top-up \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
    "customerId": "550e8400-e29b-41d4-a716-446655440000",
    "amount": 100.00,
    "currencyCode": "EUR"
  }'
```

**Response (201 Created):**

```json theme={null}
{
  "id": "top_abc123",
  "customerId": "550e8400-e29b-41d4-a716-446655440000",
  "requestedAmount": { "amount": 10000, "currencyCode": "EUR" },
  "creditedAmount": null,
  "status": "pending",
  "paymentMethodId": null,
  "createdAt": "2026-03-08T10:00:00Z",
  "completedAt": null
}
```

| Field             | Type   | Required | Description                                                                 |
| ----------------- | ------ | -------- | --------------------------------------------------------------------------- |
| `customerId`      | string | Yes      | Customer UUID                                                               |
| `amount`          | number | Yes      | Top-up amount (e.g. `100.00`)                                               |
| `currencyCode`    | string | Yes      | ISO 4217 currency code (e.g. `EUR`)                                         |
| `paymentMethodId` | string | No       | Specific payment method UUID. Defaults to customer's default payment method |

<Tip>
  The top-up creates a PaymentIntent that collects the funds. Once the payment succeeds, the amount is credited to the customer's wallet.
</Tip>

### List Top-Ups

```bash theme={null}
curl https://coreapi.io/api/wallet/top-ups?customerId=CUSTOMER_ID \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Response (200 OK):**

```json theme={null}
{
  "items": [
    {
      "id": "top_abc123",
      "customerId": "550e8400-e29b-41d4-a716-446655440000",
      "requestedAmount": { "amount": 10000, "currencyCode": "EUR" },
      "creditedAmount": { "amount": 10000, "currencyCode": "EUR" },
      "status": "completed",
      "paymentMethodId": null,
      "failureReason": null,
      "createdAt": "2026-03-08T10:00:00Z",
      "completedAt": "2026-03-08T10:01:00Z"
    }
  ],
  "count": 1
}
```

### Top-Up Status

| Status      | Description                            |
| ----------- | -------------------------------------- |
| `pending`   | Payment initiated, awaiting completion |
| `completed` | Payment succeeded, balance credited    |
| `failed`    | Payment failed, no balance change      |

### Get a Single Top-Up

```bash theme={null}
curl https://coreapi.io/api/wallet/top-ups/TOP_UP_ID \
  -H "Authorization: Bearer YOUR_API_KEY"
```

***

## Auto Top-Up Rules

Auto top-up rules automatically initiate a top-up when a customer's wallet balance drops below a configured threshold.

### Create a Rule

```bash theme={null}
curl -X POST https://coreapi.io/api/wallet/auto-top-up \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
    "customerId": "550e8400-e29b-41d4-a716-446655440000",
    "currencyCode": "EUR",
    "thresholdAmount": 10.00,
    "topUpAmount": 100.00
  }'
```

**Response (201 Created):**

```json theme={null}
{
  "id": "atr_xyz789",
  "customerId": "550e8400-e29b-41d4-a716-446655440000",
  "currencyCode": "EUR",
  "thresholdAmount": 10.00,
  "topUpAmount": 100.00,
  "paymentMethodId": null,
  "enabled": true,
  "consecutiveFailures": 0,
  "createdAt": "2026-03-08T10:00:00Z",
  "updatedAt": "2026-03-08T10:00:00Z"
}
```

| Field             | Type   | Required | Description                                               |
| ----------------- | ------ | -------- | --------------------------------------------------------- |
| `customerId`      | string | Yes      | Customer UUID                                             |
| `currencyCode`    | string | Yes      | ISO 4217 currency code                                    |
| `thresholdAmount` | number | Yes      | Balance threshold that triggers auto top-up (must be > 0) |
| `topUpAmount`     | number | Yes      | Amount to top up (must be > 0)                            |
| `paymentMethodId` | string | No       | Specific payment method. Defaults to customer's default   |

<Note>
  Only one rule per customer per currency is allowed. Attempting to create a duplicate returns `400 Bad Request`.
</Note>

### List Rules

```bash theme={null}
curl https://coreapi.io/api/wallet/auto-top-up?customerId=CUSTOMER_ID \
  -H "Authorization: Bearer YOUR_API_KEY"
```

### Update a Rule

```bash theme={null}
curl -X PUT https://coreapi.io/api/wallet/auto-top-up/RULE_ID \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
    "thresholdAmount": 20.00,
    "topUpAmount": 200.00,
    "enabled": false
  }'
```

All fields are optional — only include the fields you want to change.

| Field             | Type    | Description                     |
| ----------------- | ------- | ------------------------------- |
| `thresholdAmount` | number  | New threshold (must be > 0)     |
| `topUpAmount`     | number  | New top-up amount (must be > 0) |
| `paymentMethodId` | string  | New payment method UUID         |
| `enabled`         | boolean | Enable or disable the rule      |

### Delete a Rule

```bash theme={null}
curl -X DELETE https://coreapi.io/api/wallet/auto-top-up/RULE_ID \
  -H "Authorization: Bearer YOUR_API_KEY"
```

Returns `204 No Content` on success.

***

## How Auto Top-Up Works

1. A balance-reducing transaction occurs (e.g., wallet balance applied to an invoice)
2. Fynn checks if an enabled auto top-up rule exists for the customer and currency
3. If the ending balance is below the threshold, a top-up is initiated automatically
4. The top-up follows the same flow as a manual top-up (PaymentIntent → payment → credit)

**Safety mechanisms:**

* Top-up transactions themselves do **not** trigger auto top-up (prevents loops)
* The `consecutiveFailures` counter tracks sequential failures — monitor this to detect broken payment methods
* The feature must be enabled via the `WalletTopUp` feature flag

***

## Customer-Authenticated Requests

Customers authenticated via the customer portal can manage their own wallet:

* **Top-up**: `customerId` is inferred from the authenticated session (do not include it)
* **Auto top-up rules**: Customers can only view/manage their own rules
* Attempting to access another customer's data returns `403 Forbidden`

```bash theme={null}
# Customer-authenticated top-up (no customerId needed)
curl -X POST https://coreapi.io/api/wallet/top-up \
  -H "Authorization: Bearer CUSTOMER_TOKEN" \
  -d '{
    "amount": 50.00,
    "currencyCode": "EUR"
  }'
```

***

## Error Handling

| Status Code                | Scenario                                                           |
| -------------------------- | ------------------------------------------------------------------ |
| `400 Bad Request`          | Missing required field, duplicate rule for same currency           |
| `403 Forbidden`            | Feature not enabled, or customer accessing another customer's data |
| `404 Not Found`            | Rule or top-up not found                                           |
| `422 Unprocessable Entity` | Invalid amounts (zero, negative), invalid currency code            |

***

## Integration Example

```javascript theme={null}
const FYNN_API = 'https://coreapi.io';
const API_KEY = process.env.FYNN_API_KEY;

async function ensureWalletFunded(customerId, minBalance = 10, topUpAmount = 100) {
  // Check if auto top-up rule exists
  const rules = await fetch(
    `${FYNN_API}/api/wallet/auto-top-up?customerId=${customerId}`,
    { headers: { 'Authorization': `Bearer ${API_KEY}` } }
  ).then(r => r.json());

  if (rules.items.length === 0) {
    // Create auto top-up rule
    await fetch(`${FYNN_API}/api/wallet/auto-top-up`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${API_KEY}`,
      },
      body: JSON.stringify({
        customerId,
        currencyCode: 'EUR',
        thresholdAmount: minBalance,
        topUpAmount: topUpAmount,
      }),
    });
  }
}
```

***

## Related Documentation

* [Kundenguthaben](/guide/invoices/wallet-balance) - Wie das Wallet-Guthaben funktioniert
* [Wallet aufladen (Benutzerhandbuch)](/guide/invoices/wallet-top-up) - Schritt-für-Schritt-Anleitung
* [Zahlungsmethoden hinzufügen](/api-reference/guides/add-payment-method) - Payment method setup
